MozReview-Commit-ID: BnSh8kutBaR
This commit is contained in:
Phil Ringnalda 2016-12-10 08:27:52 -08:00
Родитель de319dfd72 18488c358f
Коммит 0111ff534b
180 изменённых файлов: 5486 добавлений и 5859 удалений

Просмотреть файл

@ -33,8 +33,7 @@ this.AccessFu = { // jshint ignore:line
Utils.init(aWindow);
try {
Services.androidBridge.handleGeckoMessage(
{ type: 'Accessibility:Ready' });
Services.androidBridge.dispatch('Accessibility:Ready');
Services.obs.addObserver(this, 'Accessibility:Settings', false);
} catch (x) {
// Not on Android
@ -602,7 +601,6 @@ var Output = {
}
for (let androidEvent of aDetails) {
androidEvent.type = 'Accessibility:Event';
if (androidEvent.bounds) {
androidEvent.bounds = AccessFu.adjustContentBounds(
androidEvent.bounds, aBrowser);
@ -622,7 +620,9 @@ var Output = {
androidEvent.brailleOutput);
break;
}
this.androidBridge.handleGeckoMessage(androidEvent);
let win = Utils.win;
let view = win && win.QueryInterface(Ci.nsIAndroidView);
view.dispatch('Accessibility:Event', androidEvent);
}
},
@ -818,8 +818,9 @@ var Input = {
if (Utils.MozBuildApp == 'mobile/android') {
// Return focus to native Android browser chrome.
Services.androidBridge.handleGeckoMessage(
{ type: 'ToggleChrome:Focus' });
let win = Utils.win;
let view = win && win.QueryInterface(Ci.nsIAndroidView);
view.dispatch('ToggleChrome:Focus');
}
break;
case aEvent.DOM_VK_RETURN:

Просмотреть файл

@ -5731,6 +5731,8 @@ nsDocShell::Destroy()
NS_ASSERTION(mItemType == typeContent || mItemType == typeChrome,
"Unexpected item type in docshell");
AssertOriginAttributesMatchPrivateBrowsing();
if (!mIsBeingDestroyed) {
nsCOMPtr<nsIObserverService> serv = services::GetObserverService();
if (serv) {
@ -14344,6 +14346,7 @@ nsDocShell::SetOriginAttributes(const DocShellOriginAttributes& aAttrs)
}
SetPrivateBrowsing(isPrivate);
AssertOriginAttributesMatchPrivateBrowsing();
return NS_OK;
}

Просмотреть файл

@ -47,6 +47,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DOMIntersectionObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRoot)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mQueuedEntries)
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DOMIntersectionObserver)
@ -185,9 +186,10 @@ DOMIntersectionObserver::Connect()
if (mConnected) {
return;
}
mConnected = true;
nsIDocument* document = mOwner->GetExtantDoc();
document->AddIntersectionObserver(this);
mConnected = true;
}
void

Просмотреть файл

@ -101,9 +101,7 @@ protected:
class DOMIntersectionObserver final : public nsISupports,
public nsWrapperCache
{
virtual ~DOMIntersectionObserver() {
Disconnect();
}
virtual ~DOMIntersectionObserver() { }
public:
DOMIntersectionObserver(already_AddRefed<nsPIDOMWindowInner>&& aOwner,

Просмотреть файл

@ -3869,7 +3869,7 @@ Element::ClearDataset()
slots->mDataset = nullptr;
}
nsTArray<Element::nsDOMSlots::IntersectionObserverRegistration>*
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>*
Element::RegisteredIntersectionObservers()
{
nsDOMSlots* slots = DOMSlots();
@ -3879,34 +3879,34 @@ Element::RegisteredIntersectionObservers()
void
Element::RegisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
RegisteredIntersectionObservers()->AppendElement(
nsDOMSlots::IntersectionObserverRegistration { aObserver, -1 });
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
if (observers->Contains(aObserver)) {
return;
}
RegisteredIntersectionObservers()->Put(aObserver, -1);
}
void
Element::UnregisterIntersectionObserver(DOMIntersectionObserver* aObserver)
{
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
for (uint32_t i = 0; i < observers->Length(); ++i) {
nsDOMSlots::IntersectionObserverRegistration reg = observers->ElementAt(i);
if (reg.observer == aObserver) {
observers->RemoveElementAt(i);
break;
}
}
observers->Remove(aObserver);
}
bool
Element::UpdateIntersectionObservation(DOMIntersectionObserver* aObserver, int32_t aThreshold)
{
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* observers =
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* observers =
RegisteredIntersectionObservers();
for (auto& reg : *observers) {
if (reg.observer == aObserver && reg.previousThreshold != aThreshold) {
reg.previousThreshold = aThreshold;
return true;
}
if (!observers->Contains(aObserver)) {
return false;
}
int32_t previousThreshold = observers->Get(aObserver);
if (previousThreshold != aThreshold) {
observers->Put(aObserver, aThreshold);
return true;
}
return false;
}

Просмотреть файл

@ -1423,7 +1423,7 @@ protected:
nsDOMTokenList* GetTokenList(nsIAtom* aAtom,
const DOMTokenListSupportedTokenArray aSupportedTokens = nullptr);
nsTArray<nsDOMSlots::IntersectionObserverRegistration>* RegisteredIntersectionObservers();
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t>* RegisteredIntersectionObservers();
private:
/**

Просмотреть файл

@ -21,6 +21,7 @@
#include "nsIWeakReference.h" // base class
#include "nsNodeUtils.h" // class member nsNodeUtils::CloneNodeImpl
#include "nsIHTMLCollection.h"
#include "nsDataHashtable.h"
class ContentUnbinder;
class nsContentList;
@ -347,12 +348,7 @@ public:
/**
* Registered Intersection Observers on the element.
*/
struct IntersectionObserverRegistration {
DOMIntersectionObserver* observer;
int32_t previousThreshold;
};
nsTArray<IntersectionObserverRegistration> mRegisteredIntersectionObservers;
nsDataHashtable<nsPtrHashKey<DOMIntersectionObserver>, int32_t> mRegisteredIntersectionObservers;
};
protected:

Просмотреть файл

@ -301,8 +301,9 @@ nsNodeUtils::LastRelease(nsINode* aNode)
Element* elem = aNode->AsElement();
FragmentOrElement::nsDOMSlots* domSlots =
static_cast<FragmentOrElement::nsDOMSlots*>(slots);
for (auto& reg : domSlots->mRegisteredIntersectionObservers) {
reg.observer->UnlinkTarget(*elem);
for (auto iter = domSlots->mRegisteredIntersectionObservers.Iter(); !iter.Done(); iter.Next()) {
DOMIntersectionObserver* observer = iter.Key();
observer->UnlinkTarget(*elem);
}
}

Просмотреть файл

@ -891,6 +891,19 @@ limitations under the License.
var win = window.open("intersectionobserver_window.html");
});
it('triggers only once if observed multiple times (and does not crash when collected)', function(done) {
var spy = sinon.spy();
io = new IntersectionObserver(spy, {root: rootEl});
io.observe(targetEl1);
io.observe(targetEl1);
io.observe(targetEl1);
callDelayed(function () {
expect(spy.callCount).to.be(1);
done();
}, ASYNC_TIMEOUT);
});
});
describe('observe subframe', function () {

Просмотреть файл

@ -35,18 +35,95 @@ function turnOnPointerEvents(callback) {
}, callback);
}
// Mouse Event Helper Object
var MouseEventHelper = (function() {
var utils = SpecialPowers.Ci.nsIDOMWindowUtils;
return {
// State
// TODO: Separate this to support mouse and pen simultaneously.
BUTTONS_STATE: utils.MOUSE_BUTTONS_NO_BUTTON,
// Button
BUTTON_NONE: -1, // Used by test framework only. (replaced before sending)
BUTTON_LEFT: utils.MOUSE_BUTTON_LEFT_BUTTON,
BUTTON_MIDDLE: utils.MOUSE_BUTTON_MIDDLE_BUTTON,
BUTTON_RIGHT: utils.MOUSE_BUTTON_RIGHT_BUTTON,
// Buttons
BUTTONS_NONE: utils.MOUSE_BUTTONS_NO_BUTTON,
BUTTONS_LEFT: utils.MOUSE_BUTTONS_LEFT_BUTTON,
BUTTONS_MIDDLE: utils.MOUSE_BUTTONS_MIDDLE_BUTTON,
BUTTONS_RIGHT: utils.MOUSE_BUTTONS_RIGHT_BUTTON,
BUTTONS_4TH: utils.MOUSE_BUTTONS_4TH_BUTTON,
BUTTONS_5TH: utils.MOUSE_BUTTONS_5TH_BUTTON,
// Utils
computeButtonsMaskFromButton: function(aButton) {
// Since the range of button values is 0 ~ 2 (see nsIDOMWindowUtils.idl),
// we can use an array to find out the desired mask.
var mask = [
this.BUTTONS_NONE, // -1 (MouseEventHelper.BUTTON_NONE)
this.BUTTONS_LEFT, // 0
this.BUTTONS_MIDDLE, // 1
this.BUTTONS_RIGHT // 2
][aButton + 1];
ok(mask !== undefined, "Unrecognized button value caught!");
return mask;
},
checkExitState: function() {
ok(!this.BUTTONS_STATE, "Mismatched mousedown/mouseup caught.");
}
};
}) ();
// Helper function to send MouseEvent with different parameters
function sendMouseEvent(int_win, elemId, mouseEventType, params) {
var elem = int_win.document.getElementById(elemId);
if(!!elem) {
var rect = elem.getBoundingClientRect();
var eventObj = {type: mouseEventType};
if(params && "button" in params)
eventObj.button = params.button;
if(params && "inputSource" in params)
eventObj.inputSource = params.inputSource;
if(params && "buttons" in params)
eventObj.buttons = params.buttons;
// Check or generate a |button| value.
var isButtonEvent = mouseEventType === "mouseup" ||
mouseEventType === "mousedown";
// Set |button| to the default value first.
eventObj.button = isButtonEvent ? MouseEventHelper.BUTTON_LEFT
: MouseEventHelper.BUTTON_NONE;
// |button| is passed, use and check it.
if (params && "button" in params) {
var hasButtonValue = (params.button !== MouseEventHelper.BUTTON_NONE);
ok(!isButtonEvent || hasButtonValue,
"Inappropriate |button| value caught.");
eventObj.button = params.button;
}
// Generate a |buttons| value and update buttons state
var buttonsMask = MouseEventHelper.computeButtonsMaskFromButton(eventObj.button);
switch(mouseEventType) {
case "mousedown":
MouseEventHelper.BUTTONS_STATE |= buttonsMask; // Set button flag.
break;
case "mouseup":
MouseEventHelper.BUTTONS_STATE &= ~buttonsMask; // Clear button flag.
break;
}
eventObj.buttons = MouseEventHelper.BUTTONS_STATE;
// Replace the button value for mousemove events.
// Since in widget level design, even when no button is pressed at all, the
// value of WidgetMouseEvent.button is still 0, which is the same value as
// the one for mouse left button.
if (mouseEventType === "mousemove") {
eventObj.button = MouseEventHelper.BUTTON_LEFT;
}
// Default to the center of the target element but we can still send to a
// position outside of the target element.
@ -61,6 +138,18 @@ function sendMouseEvent(int_win, elemId, mouseEventType, params) {
}
}
// Touch Event Helper Object
var TouchEventHelper = {
// State
// TODO: Support multiple point scenarios.
TOUCH_STATE: false,
// Utils
checkExitState: function() {
ok(!this.TOUCH_STATE, "Mismatched touchstart/touchend caught.");
}
}
// Helper function to send TouchEvent with different parameters
function sendTouchEvent(int_win, elemId, touchEventType, params) {
var elem = int_win.document.getElementById(elemId);
@ -68,6 +157,16 @@ function sendTouchEvent(int_win, elemId, touchEventType, params) {
var rect = elem.getBoundingClientRect();
var eventObj = {type: touchEventType};
// Update touch state
switch(touchEventType) {
case "touchstart":
TouchEventHelper.TOUCH_STATE = true; // Set touch flag.
break;
case "touchend":
TouchEventHelper.TOUCH_STATE = false; // Clear touch flag.
break;
}
// Default to the center of the target element but we can still send to a
// position outside of the target element.
var offsetX = params && "offsetX" in params ? params.offsetX : rect.width / 2;
@ -82,42 +181,25 @@ function sendTouchEvent(int_win, elemId, touchEventType, params) {
// Helper function to run Point Event test in a new tab.
function runTestInNewWindow(aFile) {
var w = window.open('', "_blank");
w.is = function(a, b, msg) { return is(a, b, aFile + " | " + msg); };
w.ok = function(cond, name, diag) { return ok(cond, aFile + " | " + name, diag); };
w.location = location.href.substring(0, location.href.lastIndexOf('/') + 1) + aFile;
var testURL = location.href.substring(0, location.href.lastIndexOf('/') + 1) + aFile;
var testWindow = window.open(testURL, "_blank");
w.testContext = {
result_callback: (aTestObj) => {
if(aTestObj["status"] != aTestObj["PASS"]) {
console.log(aTestObj["status"] + " = " + aTestObj["PASS"] + ". " + aTestObj["name"]);
}
is(aTestObj["status"], aTestObj["PASS"], aTestObj["name"]);
},
completion_callback: () => {
if (!!w.testContext.executionPromise) {
// We need to wait tests done and execute finished then we can close the window
w.testContext.executionPromise.then(() => {
w.close();
SimpleTest.finish();
});
} else {
// execute may synchronous trigger tests done. In that case executionPromise
// is not yet assigned
w.close();
SimpleTest.finish();
}
},
execute: (aWindow) => {
turnOnPointerEvents(() => {
w.testContext.executionPromise = new Promise((aResolve, aReject) => {
executeTest(aWindow);
aResolve();
window.addEventListener("message", function(aEvent) {
switch(aEvent.data.type) {
case "START":
turnOnPointerEvents(() => {
executeTest(testWindow);
});
});
return;
case "RESULT":
ok(aEvent.data.result, aEvent.data.message);
return;
case "FIN":
MouseEventHelper.checkExitState();
TouchEventHelper.checkExitState();
testWindow.close();
SimpleTest.finish();
return;
}
};
return w;
});
}

Просмотреть файл

@ -2,21 +2,34 @@
// to tests on auto MochiTest system with minimum changes.
// Author: Maksim Lebedev <alessarik@gmail.com>
// Function allows to prepare our tests after load document
addEventListener("load", function(event) {
const PARENT_ORIGIN = "http://mochi.test:8888/";
addEventListener("load", function() {
// Setup environment.
console.log("OnLoad internal document");
addListeners(document.getElementById("target0"));
addListeners(document.getElementById("target1"));
preExecute();
}, false);
// Function allows to initialize prerequisites before testing
// and adds some callbacks to support mochitest system.
function preExecute() {
add_result_callback(testContext.result_callback);
add_completion_callback(testContext.completion_callback);
testContext.execute(window);
}
// Setup communication between mochitest_support_external.js.
// Function allows to initialize prerequisites before testing
// and adds some callbacks to support mochitest system.
add_result_callback((aTestObj) => {
var message = aTestObj["name"] + " (";
message += "Get: " + JSON.stringify(aTestObj["status"]) + ", ";
message += "Expect: " + JSON.stringify(aTestObj["PASS"]) + ")";
window.opener.postMessage({type: "RESULT",
message: message,
result: aTestObj["status"] === aTestObj["PASS"]},
PARENT_ORIGIN);
});
add_completion_callback(() => {
window.opener.postMessage({type: "FIN"}, PARENT_ORIGIN);
});
// Start testing.
window.opener.postMessage({type: "START"}, PARENT_ORIGIN);
});
function addListeners(elem) {
if(!elem)

Просмотреть файл

@ -17,13 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_attributes_mouse-manual.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "square1", "mousemove", {button:-1});
sendMouseEvent(int_win, "square1", "mousedown", {button:0});
sendMouseEvent(int_win, "square1", "mouseup", {button:0});
sendMouseEvent(int_win, "square1", "mousemove", {button:-1});
sendMouseEvent(int_win, "square1", "mousemove", {button:-1,
offsetX: -1,
offsetY: -1});
sendMouseEvent(int_win, "square1", "mousemove");
sendMouseEvent(int_win, "square1", "mousedown");
sendMouseEvent(int_win, "square1", "mouseup");
sendMouseEvent(int_win, "square1", "mousemove");
sendMouseEvent(int_win, "square1", "mousemove", {offsetX: -1, offSetY: -1});
}
</script>
</head>

Просмотреть файл

@ -20,7 +20,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
sendMouseEvent(int_win, "btnCapture", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:1});
sendMouseEvent(int_win, "btnCapture", "mousedown");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target1", "mouseup");
sendMouseEvent(int_win, "target1", "mousemove");

Просмотреть файл

@ -19,7 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:1});
sendMouseEvent(int_win, "btnCapture", "mousedown");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");

Просмотреть файл

@ -18,12 +18,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target1", "mouseup");
sendMouseEvent(int_win, "target1", "mousedown");
sendMouseEvent(int_win, "target1", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -18,10 +18,10 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target1", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_gotpointercapture_before_first_pointerevent-manual.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -22,6 +22,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
sendMouseEvent(int_win, "btnCapture", "mousemove");
setTimeout(function() {
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target1", "mouseup");
}, 500);
}
</script>

Просмотреть файл

@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_lostpointercapture_is_first-manual.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "btnCapture", "mousedown", {button:0});
sendMouseEvent(int_win, "btnCapture", "mouseup", {button:0});
sendMouseEvent(int_win, "btnCapture", "mousedown");
sendMouseEvent(int_win, "btnCapture", "mouseup");
sendMouseEvent(int_win, "btnCapture", "mousemove");
}
</script>

Просмотреть файл

@ -21,8 +21,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
sendTouchEvent(int_win, "target1", "touchstart");
sendTouchEvent(int_win, "target1", "touchend");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "done", "mousedown", {button:0});
sendMouseEvent(int_win, "done", "mouseup", {button:0});
sendMouseEvent(int_win, "done", "mousedown");
sendMouseEvent(int_win, "done", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendTouchEvent(int_win, "target0", "touchstart");
sendTouchEvent(int_win, "target0", "touchcancel");
// Need a touchend event to terminated the test gracefully.
sendTouchEvent(int_win, "target0", "touchend");
}
</script>
</head>

Просмотреть файл

@ -18,7 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "log", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:1});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>

Просмотреть файл

@ -18,6 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendTouchEvent(int_win, "target0", "touchstart");
sendTouchEvent(int_win, "target0", "touchcancel");
// Need a touchend event to terminated the test gracefully.
sendTouchEvent(int_win, "target0", "touchend");
}
</script>
</head>

Просмотреть файл

@ -18,17 +18,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
var utils = _getDOMWindowUtils(int_win);
sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
sendMouseEvent(int_win, "target0", "mousedown", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
sendMouseEvent(int_win, "target0", "mousemove", {button:0, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
sendMouseEvent(int_win, "target0", "mousedown", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON |
utils.MOUSE_BUTTONS_MIDDLE_BUTTON});
sendMouseEvent(int_win, "target0", "mouseup", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
sendMouseEvent(int_win, "target0", "mousemove", {button:1, buttons:utils.MOUSE_BUTTONS_LEFT_BUTTON});
sendMouseEvent(int_win, "target0", "mouseup", {button:0, buttons:utils.MOUSE_BUTTONS_NO_BUTTON});
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button: MouseEventHelper.BUTTON_LEFT});
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button: MouseEventHelper.BUTTON_MIDDLE});
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup", {button: MouseEventHelper.BUTTON_MIDDLE});
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup", {button: MouseEventHelper.BUTTON_LEFT});
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendTouchEvent(int_win, "target0", "touchstart");
sendTouchEvent(int_win, "target0", "touchcancel");
// Need a touchend event to terminated the test gracefully.
sendTouchEvent(int_win, "target0", "touchend");
}
</script>
</head>

Просмотреть файл

@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_pointertype_mouse-manual.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_pointerup_isprimary_same_as_pointerdown-manual.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendTouchEvent(int_win, "target0", "touchstart");
sendTouchEvent(int_win, "target0", "touchmove");
// Need a touchend event to terminated the test gracefully.
sendTouchEvent(int_win, "target0", "touchend");
}
</script>
</head>

Просмотреть файл

@ -19,6 +19,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
function executeTest(int_win) {
sendTouchEvent(int_win, "target0", "touchstart");
sendTouchEvent(int_win, "target0", "touchcancel");
// Need a touchend event to terminated the test gracefully.
sendTouchEvent(int_win, "target0", "touchend");
}
</script>
</head>

Просмотреть файл

@ -17,11 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -18,6 +18,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -18,11 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -18,11 +18,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -17,12 +17,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_suppress_compat_events_on_click.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
sendMouseEvent(int_win, "done", "mousedown", {button:0});
sendMouseEvent(int_win, "done", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mouseup");
sendMouseEvent(int_win, "target1", "mousedown");
sendMouseEvent(int_win, "target1", "mouseup");
sendMouseEvent(int_win, "done", "mousedown");
sendMouseEvent(int_win, "done", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -17,14 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1000870
runTestInNewWindow("pointerevent_suppress_compat_events_on_drag_mouse.html");
}
function executeTest(int_win) {
sendMouseEvent(int_win, "target0", "mousedown", {button:0});
sendMouseEvent(int_win, "target0", "mousemove", {button:0});
sendMouseEvent(int_win, "target0", "mouseup", {button:0});
sendMouseEvent(int_win, "target1", "mousedown", {button:0});
sendMouseEvent(int_win, "target1", "mousemove", {button:0});
sendMouseEvent(int_win, "target1", "mouseup", {button:0});
sendMouseEvent(int_win, "done", "mousedown", {button:0});
sendMouseEvent(int_win, "done", "mouseup", {button:0});
sendMouseEvent(int_win, "target0", "mousedown");
sendMouseEvent(int_win, "target0", "mousemove");
sendMouseEvent(int_win, "target0", "mouseup");
sendMouseEvent(int_win, "target1", "mousedown");
sendMouseEvent(int_win, "target1", "mousemove");
sendMouseEvent(int_win, "target1", "mouseup");
sendMouseEvent(int_win, "done", "mousedown");
sendMouseEvent(int_win, "done", "mouseup");
}
</script>
</head>

Просмотреть файл

@ -1973,6 +1973,12 @@ interface nsIDOMWindowUtils : nsISupports {
*/
readonly attribute int32_t gpuProcessPid;
// Match WidgetMouseEventBase::buttonType.
const long MOUSE_BUTTON_LEFT_BUTTON = 0;
const long MOUSE_BUTTON_MIDDLE_BUTTON = 1;
const long MOUSE_BUTTON_RIGHT_BUTTON = 2;
// Match WidgetMouseEventBase::buttonsFlag.
const long MOUSE_BUTTONS_NO_BUTTON = 0x00;
const long MOUSE_BUTTONS_LEFT_BUTTON = 0x01;
const long MOUSE_BUTTONS_RIGHT_BUTTON = 0x02;

Просмотреть файл

@ -4,7 +4,7 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
SOURCES += [
UNIFIED_SOURCES += [
'mozHunspell.cpp',
'mozHunspellDirProvider.cpp',
'RemoteSpellCheckEngineChild.cpp',

Просмотреть файл

@ -200,7 +200,7 @@ NS_IMETHODIMP mozHunspell::SetDictionary(const char16_t *aDictionary)
if (!mHunspell)
return NS_ERROR_OUT_OF_MEMORY;
nsDependentCString label(mHunspell->get_dic_encoding());
nsAutoCString label(mHunspell->get_dict_encoding().c_str());
nsAutoCString encoding;
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
return NS_ERROR_UCONV_NOCONV;
@ -480,7 +480,8 @@ mozHunspell::LoadDictionariesFromDir(nsIFile* aDir)
return NS_OK;
}
nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
nsresult
mozHunspell::ConvertCharset(const char16_t* aStr, std::string* aDst)
{
NS_ENSURE_ARG_POINTER(aDst);
NS_ENSURE_TRUE(mEncoder, NS_ERROR_NULL_POINTER);
@ -490,12 +491,13 @@ nsresult mozHunspell::ConvertCharset(const char16_t* aStr, char ** aDst)
nsresult rv = mEncoder->GetMaxLength(aStr, inLength, &outLength);
NS_ENSURE_SUCCESS(rv, rv);
*aDst = (char *) moz_xmalloc(sizeof(char) * (outLength+1));
NS_ENSURE_TRUE(*aDst, NS_ERROR_OUT_OF_MEMORY);
aDst->resize(outLength);
rv = mEncoder->Convert(aStr, &inLength, *aDst, &outLength);
if (NS_SUCCEEDED(rv))
(*aDst)[outLength] = '\0';
char* dst = &aDst->operator[](0);
rv = mEncoder->Convert(aStr, &inLength, dst, &outLength);
if (NS_SUCCEEDED(rv)) {
aDst->resize(outLength);
}
return rv;
}
@ -518,12 +520,11 @@ NS_IMETHODIMP mozHunspell::Check(const char16_t *aWord, bool *aResult)
NS_ENSURE_ARG_POINTER(aResult);
NS_ENSURE_TRUE(mHunspell, NS_ERROR_FAILURE);
nsXPIDLCString charsetWord;
nsresult rv = ConvertCharset(aWord, getter_Copies(charsetWord));
std::string charsetWord;
nsresult rv = ConvertCharset(aWord, &charsetWord);
NS_ENSURE_SUCCESS(rv, rv);
*aResult = !!mHunspell->spell(charsetWord);
*aResult = mHunspell->spell(charsetWord);
if (!*aResult && mPersonalDictionary)
rv = mPersonalDictionary->Check(aWord, mLanguage.get(), aResult);
@ -540,12 +541,12 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
nsresult rv;
*aSuggestionCount = 0;
nsXPIDLCString charsetWord;
rv = ConvertCharset(aWord, getter_Copies(charsetWord));
std::string charsetWord;
rv = ConvertCharset(aWord, &charsetWord);
NS_ENSURE_SUCCESS(rv, rv);
char ** wlst;
*aSuggestionCount = mHunspell->suggest(&wlst, charsetWord);
std::vector<std::string> suggestions = mHunspell->suggest(charsetWord);
*aSuggestionCount = static_cast<uint32_t>(suggestions.size());
if (*aSuggestionCount) {
*aSuggestions = (char16_t **)moz_xmalloc(*aSuggestionCount * sizeof(char16_t *));
@ -553,15 +554,15 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
uint32_t index = 0;
for (index = 0; index < *aSuggestionCount && NS_SUCCEEDED(rv); ++index) {
// Convert the suggestion to utf16
int32_t inLength = strlen(wlst[index]);
int32_t inLength = suggestions[index].size();
int32_t outLength;
rv = mDecoder->GetMaxLength(wlst[index], inLength, &outLength);
rv = mDecoder->GetMaxLength(suggestions[index].c_str(), inLength, &outLength);
if (NS_SUCCEEDED(rv))
{
(*aSuggestions)[index] = (char16_t *) moz_xmalloc(sizeof(char16_t) * (outLength+1));
if ((*aSuggestions)[index])
{
rv = mDecoder->Convert(wlst[index], &inLength, (*aSuggestions)[index], &outLength);
rv = mDecoder->Convert(suggestions[index].c_str(), &inLength, (*aSuggestions)[index], &outLength);
if (NS_SUCCEEDED(rv))
(*aSuggestions)[index][outLength] = 0;
}
@ -577,7 +578,6 @@ NS_IMETHODIMP mozHunspell::Suggest(const char16_t *aWord, char16_t ***aSuggestio
rv = NS_ERROR_OUT_OF_MEMORY;
}
NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(*aSuggestionCount, wlst);
return rv;
}

Просмотреть файл

@ -99,7 +99,7 @@ public:
void LoadDictionaryList(bool aNotifyChildProcesses);
// helper method for converting a word to the charset of the dictionary
nsresult ConvertCharset(const char16_t* aStr, char ** aDst);
nsresult ConvertCharset(const char16_t* aStr, std::string* aDst);
NS_DECL_NSIMEMORYREPORTER

Просмотреть файл

@ -1,2 +1,2 @@
Hunspell Version: 1.4.1
Hunspell Version: 1.5.4
Additional Patches: See patches directory.

Просмотреть файл

@ -79,33 +79,7 @@
#include "affentry.hxx"
#include "csutil.hxx"
PfxEntry::PfxEntry(AffixMgr* pmgr, affentry* dp)
// register affix manager
: pmyMgr(pmgr),
next(NULL),
nexteq(NULL),
nextne(NULL),
flgnxt(NULL) {
// set up its initial values
aflag = dp->aflag; // flag
strip = dp->strip; // string to strip
appnd = dp->appnd; // string to append
numconds = dp->numconds; // length of the condition
opts = dp->opts; // cross product flag
// then copy over all of the conditions
if (opts & aeLONGCOND) {
memcpy(c.conds, dp->c.l.conds1, MAXCONDLEN_1);
c.l.conds2 = dp->c.l.conds2;
} else
memcpy(c.conds, dp->c.conds, MAXCONDLEN);
morphcode = dp->morphcode;
contclass = dp->contclass;
contclasslen = dp->contclasslen;
}
PfxEntry::~PfxEntry() {
aflag = 0;
pmyMgr = NULL;
AffEntry::~AffEntry() {
if (opts & aeLONGCOND)
free(c.l.conds2);
if (morphcode && !(opts & aeALIASM))
@ -114,17 +88,26 @@ PfxEntry::~PfxEntry() {
free(contclass);
}
PfxEntry::PfxEntry(AffixMgr* pmgr)
// register affix manager
: pmyMgr(pmgr),
next(NULL),
nexteq(NULL),
nextne(NULL),
flgnxt(NULL) {
}
// add prefix to this word assuming conditions hold
char* PfxEntry::add(const char* word, size_t len) {
std::string PfxEntry::add(const char* word, size_t len) {
std::string result;
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
(len >= numconds) && test_condition(word) &&
(!strip.size() || (strncmp(word, strip.c_str(), strip.size()) == 0))) {
/* we have a match so add prefix */
std::string tword(appnd);
tword.append(word + strip.size());
return mystrdup(tword.c_str());
result.assign(appnd);
result.append(word + strip.size());
}
return NULL;
return result;
}
inline char* PfxEntry::nextchar(char* p) {
@ -276,8 +259,7 @@ struct hentry* PfxEntry::checkword(const char* word,
// if ((opts & aeXPRODUCT) && in_compound) {
if ((opts & aeXPRODUCT)) {
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, aeXPRODUCT, this,
NULL, 0, NULL, FLAG_NULL, needflag,
in_compound);
FLAG_NULL, needflag, in_compound);
if (he)
return he;
}
@ -291,8 +273,6 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
int len,
char in_compound,
const FLAG needflag) {
struct hentry* he; // hash entry of root word or NULL
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
@ -324,8 +304,9 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
// cross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
needflag);
// hash entry of root word or NULL
struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this,
needflag);
if (he)
return he;
}
@ -335,15 +316,15 @@ struct hentry* PfxEntry::check_twosfx(const char* word,
}
// check if this prefix entry matches
char* PfxEntry::check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag) {
std::string PfxEntry::check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag) {
std::string result;
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
// and if there are enough chars in root word and added back strip chars
// to meet the number of characters conditions, then test it
int tmpl = len - appnd.size(); // length of tmpword
if ((tmpl > 0 || (tmpl == 0 && pmyMgr->get_fullstrip())) &&
@ -370,22 +351,21 @@ char* PfxEntry::check_twosfx_morph(const char* word,
// ross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
return pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
aeXPRODUCT,
this, needflag);
result = pmyMgr->suffix_check_twosfx_morph(tmpword.c_str(), tmpl,
aeXPRODUCT,
this, needflag);
}
}
}
return NULL;
return result;
}
// check if this prefix entry matches
char* PfxEntry::check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag) {
struct hentry* he; // hash entry of root word or NULL
char* st;
std::string PfxEntry::check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag) {
std::string result;
// on entry prefix is 0 length or already matches the beginning of the word.
// So if the remaining root word has positive length
@ -411,9 +391,8 @@ char* PfxEntry::check_morph(const char* word,
// root word in the dictionary
if (test_condition(tmpword.c_str())) {
std::string result;
tmpl += strip.size();
struct hentry* he; // hash entry of root word or NULL
if ((he = pmyMgr->lookup(tmpword.c_str())) != NULL) {
do {
if (TESTAFF(he->astr, aflag, he->alen) &&
@ -455,23 +434,19 @@ char* PfxEntry::check_morph(const char* word,
// ross checked combined with a suffix
if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) {
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
FLAG_NULL, needflag);
if (st) {
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, aeXPRODUCT, this,
FLAG_NULL, needflag);
if (!st.empty()) {
result.append(st);
free(st);
}
}
if (!result.empty())
return mystrdup(result.c_str());
}
}
return NULL;
return result;
}
SfxEntry::SfxEntry(AffixMgr* pmgr, affentry* dp)
SfxEntry::SfxEntry(AffixMgr* pmgr)
: pmyMgr(pmgr) // register affix manager
,
next(NULL),
@ -481,50 +456,21 @@ SfxEntry::SfxEntry(AffixMgr* pmgr, affentry* dp)
l_morph(NULL),
r_morph(NULL),
eq_morph(NULL) {
// set up its initial values
aflag = dp->aflag; // char flag
strip = dp->strip; // string to strip
appnd = dp->appnd; // string to append
numconds = dp->numconds; // length of the condition
opts = dp->opts; // cross product flag
// then copy over all of the conditions
if (opts & aeLONGCOND) {
memcpy(c.l.conds1, dp->c.l.conds1, MAXCONDLEN_1);
c.l.conds2 = dp->c.l.conds2;
} else
memcpy(c.conds, dp->c.conds, MAXCONDLEN);
rappnd = appnd;
reverseword(rappnd);
morphcode = dp->morphcode;
contclass = dp->contclass;
contclasslen = dp->contclasslen;
}
SfxEntry::~SfxEntry() {
aflag = 0;
pmyMgr = NULL;
if (opts & aeLONGCOND)
free(c.l.conds2);
if (morphcode && !(opts & aeALIASM))
free(morphcode);
if (contclass && !(opts & aeALIASF))
free(contclass);
}
// add suffix to this word assuming conditions hold
char* SfxEntry::add(const char* word, size_t len) {
std::string SfxEntry::add(const char* word, size_t len) {
std::string result;
/* make sure all conditions match */
if ((len > strip.size() || (len == 0 && pmyMgr->get_fullstrip())) &&
(len >= numconds) && test_condition(word + len, word) &&
(!strip.size() ||
(strcmp(word + len - strip.size(), strip.c_str()) == 0))) {
std::string tword(word);
result.assign(word);
/* we have a match so add suffix */
tword.replace(len - strip.size(), std::string::npos, appnd);
return mystrdup(tword.c_str());
result.replace(len - strip.size(), std::string::npos, appnd);
}
return NULL;
return result;
}
inline char* SfxEntry::nextchar(char* p) {
@ -669,9 +615,6 @@ struct hentry* SfxEntry::checkword(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
char** wlst,
int maxSug,
int* ns,
const FLAG cclass,
const FLAG needflag,
const FLAG badflag) {
@ -742,27 +685,6 @@ struct hentry* SfxEntry::checkword(const char* word,
return he;
he = he->next_homonym; // check homonyms
} while (he);
// obsolote stemming code (used only by the
// experimental SuffixMgr:suggest_pos_stems)
// store resulting root in wlst
} else if (wlst && (*ns < maxSug)) {
int cwrd = 1;
for (int k = 0; k < *ns; k++)
if (strcmp(tmpword, wlst[k]) == 0) {
cwrd = 0;
break;
}
if (cwrd) {
wlst[*ns] = mystrdup(tmpword);
if (wlst[*ns] == NULL) {
for (int j = 0; j < *ns; j++)
free(wlst[j]);
*ns = -1;
return NULL;
}
(*ns)++;
}
}
}
}
@ -775,7 +697,6 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
int optflags,
PfxEntry* ppfx,
const FLAG needflag) {
struct hentry* he; // hash entry pointer
PfxEntry* ep = ppfx;
// if this suffix is being cross checked with a prefix
@ -813,17 +734,18 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
// if all conditions are met then recall suffix_check
if (test_condition(end, beg)) {
struct hentry* he; // hash entry pointer
if (ppfx) {
// handle conditional suffix
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen))
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
(FLAG)aflag, needflag);
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
(FLAG)aflag, needflag, IN_CPD_NOT);
else
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx, NULL, 0,
NULL, (FLAG)aflag, needflag);
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, optflags, ppfx,
(FLAG)aflag, needflag, IN_CPD_NOT);
} else {
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL, NULL, 0, NULL,
(FLAG)aflag, needflag);
he = pmyMgr->suffix_check(tmpword.c_str(), tmpl, 0, NULL,
(FLAG)aflag, needflag, IN_CPD_NOT);
}
if (he)
return he;
@ -833,23 +755,20 @@ struct hentry* SfxEntry::check_twosfx(const char* word,
}
// see if two-level suffix is present in the word
char* SfxEntry::check_twosfx_morph(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag) {
std::string SfxEntry::check_twosfx_morph(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag) {
PfxEntry* ep = ppfx;
char* st;
char result[MAXLNLEN];
*result = '\0';
std::string result;
// if this suffix is being cross checked with a prefix
// but it does not support cross products skip it
if ((optflags & aeXPRODUCT) != 0 && (opts & aeXPRODUCT) == 0)
return NULL;
return result;
// upon entry suffix is 0 length or already matches the end of the word.
// So if the remaining root word has positive length
@ -883,40 +802,34 @@ char* SfxEntry::check_twosfx_morph(const char* word,
if (ppfx) {
// handle conditional suffix
if ((contclass) && TESTAFF(contclass, ep->getFlag(), contclasslen)) {
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
needflag);
if (st) {
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag,
needflag);
if (!st.empty()) {
if (ppfx->getMorph()) {
mystrcat(result, ppfx->getMorph(), MAXLNLEN);
mystrcat(result, " ", MAXLNLEN);
result.append(ppfx->getMorph());
result.append(" ");
}
mystrcat(result, st, MAXLNLEN);
free(st);
result.append(st);
mychomp(result);
}
} else {
st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
needflag);
if (st) {
mystrcat(result, st, MAXLNLEN);
free(st);
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, optflags, ppfx, aflag,
needflag);
if (!st.empty()) {
result.append(st);
mychomp(result);
}
}
} else {
st =
pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
if (st) {
mystrcat(result, st, MAXLNLEN);
free(st);
std::string st = pmyMgr->suffix_check_morph(tmpword.c_str(), tmpl, 0, NULL, aflag, needflag);
if (!st.empty()) {
result.append(st);
mychomp(result);
}
}
if (*result)
return mystrdup(result);
}
}
return NULL;
return result;
}
// get next homonym with same affix
@ -948,6 +861,11 @@ struct hentry* SfxEntry::get_next_homonym(struct hentry* he,
return NULL;
}
void SfxEntry::initReverseWord() {
rappnd = appnd;
reverseword(rappnd);
}
#if 0
Appendix: Understanding Affix Code

Просмотреть файл

@ -71,10 +71,8 @@
* SUCH DAMAGE.
*/
#ifndef _AFFIX_HXX_
#define _AFFIX_HXX_
#include "hunvisapi.h"
#ifndef AFFIX_HXX_
#define AFFIX_HXX_
#include "atypes.hxx"
#include "baseaffix.hxx"
@ -82,7 +80,7 @@
/* A Prefix Entry */
class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
class PfxEntry : public AffEntry {
private:
PfxEntry(const PfxEntry&);
PfxEntry& operator=(const PfxEntry&);
@ -96,10 +94,9 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
PfxEntry* flgnxt;
public:
PfxEntry(AffixMgr* pmgr, affentry* dp);
~PfxEntry();
explicit PfxEntry(AffixMgr* pmgr);
inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
struct hentry* checkword(const char* word,
int len,
char in_compound,
@ -110,19 +107,19 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
char in_compound,
const FLAG needflag = FLAG_NULL);
char* check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
std::string check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
char* check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
std::string check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
inline FLAG getFlag() { return aflag; }
inline const char* getKey() { return appnd.c_str(); }
char* add(const char* word, size_t len);
FLAG getFlag() { return aflag; }
const char* getKey() { return appnd.c_str(); }
std::string add(const char* word, size_t len);
inline short getKeyLen() { return appnd.size(); }
@ -147,7 +144,7 @@ class LIBHUNSPELL_DLL_EXPORTED PfxEntry : protected AffEntry {
/* A Suffix Entry */
class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
class SfxEntry : public AffEntry {
private:
SfxEntry(const SfxEntry&);
SfxEntry& operator=(const SfxEntry&);
@ -166,20 +163,16 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
SfxEntry* eq_morph;
public:
SfxEntry(AffixMgr* pmgr, affentry* dp);
~SfxEntry();
explicit SfxEntry(AffixMgr* pmgr);
inline bool allowCross() { return ((opts & aeXPRODUCT) != 0); }
bool allowCross() const { return ((opts & aeXPRODUCT) != 0); }
struct hentry* checkword(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
char** wlst,
int maxSug,
int* ns,
const FLAG cclass = FLAG_NULL,
const FLAG needflag = FLAG_NULL,
const FLAG badflag = FLAG_NULL);
const FLAG cclass,
const FLAG needflag,
const FLAG badflag);
struct hentry* check_twosfx(const char* word,
int len,
@ -187,11 +180,11 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
char* check_twosfx_morph(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
std::string check_twosfx_morph(const char* word,
int len,
int optflags,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
struct hentry* get_next_homonym(struct hentry* he);
struct hentry* get_next_homonym(struct hentry* word,
int optflags,
@ -199,9 +192,9 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
const FLAG cclass,
const FLAG needflag);
inline FLAG getFlag() { return aflag; }
inline const char* getKey() { return rappnd.c_str(); }
char* add(const char* word, size_t len);
FLAG getFlag() { return aflag; }
const char* getKey() { return rappnd.c_str(); }
std::string add(const char* word, size_t len);
inline const char* getMorph() { return morphcode; }
@ -224,6 +217,7 @@ class LIBHUNSPELL_DLL_EXPORTED SfxEntry : protected AffEntry {
inline void setNextNE(SfxEntry* ptr) { nextne = ptr; }
inline void setNextEQ(SfxEntry* ptr) { nexteq = ptr; }
inline void setFlgNxt(SfxEntry* ptr) { flgnxt = ptr; }
void initReverseWord();
inline char* nextchar(char* p);
inline int test_condition(const char* st, const char* begin);

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -71,14 +71,13 @@
* SUCH DAMAGE.
*/
#ifndef _AFFIXMGR_HXX_
#define _AFFIXMGR_HXX_
#include "hunvisapi.h"
#ifndef AFFIXMGR_HXX_
#define AFFIXMGR_HXX_
#include <stdio.h>
#include <string>
#include <vector>
#include "atypes.hxx"
#include "baseaffix.hxx"
@ -93,17 +92,16 @@
class PfxEntry;
class SfxEntry;
class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
class AffixMgr {
PfxEntry* pStart[SETSIZE];
SfxEntry* sStart[SETSIZE];
PfxEntry* pFlag[SETSIZE];
SfxEntry* sFlag[SETSIZE];
HashMgr* pHMgr;
HashMgr** alldic;
int* maxdic;
char* keystring;
char* trystring;
char* encoding;
const std::vector<HashMgr*>& alldic;
const HashMgr* pHMgr;
std::string keystring;
std::string trystring;
std::string encoding;
struct cs_info* csconv;
int utf8;
int complexprefixes;
@ -125,19 +123,19 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
FLAG nongramsuggest;
FLAG needaffix;
int cpdmin;
int numrep;
replentry* reptable;
bool parsedrep;
std::vector<replentry> reptable;
RepList* iconvtable;
RepList* oconvtable;
int nummap;
mapentry* maptable;
int numbreak;
char** breaktable;
int numcheckcpd;
patentry* checkcpdtable;
bool parsedmaptable;
std::vector<mapentry> maptable;
bool parsedbreaktable;
std::vector<std::string> breaktable;
bool parsedcheckcpd;
std::vector<patentry> checkcpdtable;
int simplifiedcpd;
int numdefcpd;
flagentry* defcpdtable;
bool parseddefcpd;
std::vector<flagentry> defcpdtable;
phonetable* phone;
int maxngramsugs;
int maxcpdsugs;
@ -147,10 +145,9 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
int sugswithdots;
int cpdwordmax;
int cpdmaxsyllable;
char* cpdvowels;
w_char* cpdvowels_utf16;
int cpdvowels_utf16_len;
char* cpdsyllablenum;
std::string cpdvowels; // vowels (for calculating of Hungarian compounding limit,
std::vector<w_char> cpdvowels_utf16; //vowels for UTF-8 encoding
std::string cpdsyllablenum; // syllable count incrementing flag
const char* pfxappnd; // BUG: not stateless
const char* sfxappnd; // BUG: not stateless
int sfxextra; // BUG: not stateless
@ -159,12 +156,12 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
SfxEntry* sfx; // BUG: not stateless
PfxEntry* pfx; // BUG: not stateless
int checknum;
char* wordchars;
std::string wordchars; // letters + spec. word characters
std::vector<w_char> wordchars_utf16;
char* ignorechars;
std::string ignorechars; // letters + spec. word characters
std::vector<w_char> ignorechars_utf16;
char* version;
char* lang;
std::string version; // affix and dictionary file version string
std::string lang; // language
int langnum;
FLAG lemma_present;
FLAG circumfix;
@ -182,7 +179,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
// affix)
public:
AffixMgr(const char* affpath, HashMgr** ptr, int* md, const char* key = NULL);
AffixMgr(const char* affpath, const std::vector<HashMgr*>& ptr, const char* key = NULL);
~AffixMgr();
struct hentry* affix_check(const char* word,
int len,
@ -202,9 +199,6 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
int len,
int sfxopts,
PfxEntry* ppfx,
char** wlst,
int maxSug,
int* ns,
const FLAG cclass = FLAG_NULL,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
@ -214,39 +208,39 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
char* affix_check_morph(const char* word,
int len,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
char* prefix_check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
char* suffix_check_morph(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
const FLAG cclass = FLAG_NULL,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
std::string affix_check_morph(const char* word,
int len,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
std::string prefix_check_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
std::string suffix_check_morph(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
const FLAG cclass = FLAG_NULL,
const FLAG needflag = FLAG_NULL,
char in_compound = IN_CPD_NOT);
char* prefix_check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
char* suffix_check_twosfx_morph(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
std::string prefix_check_twosfx_morph(const char* word,
int len,
char in_compound,
const FLAG needflag = FLAG_NULL);
std::string suffix_check_twosfx_morph(const char* word,
int len,
int sfxopts,
PfxEntry* ppfx,
const FLAG needflag = FLAG_NULL);
char* morphgen(const char* ts,
int wl,
const unsigned short* ap,
unsigned short al,
const char* morph,
const char* targetmorph,
int level);
std::string morphgen(const char* ts,
int wl,
const unsigned short* ap,
unsigned short al,
const char* morph,
const char* targetmorph,
int level);
int expand_rootword(struct guessword* wlst,
int maxn,
@ -273,8 +267,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
int cpdcase_check(const char* word, int len);
inline int candidate_check(const char* word, int len);
void setcminmax(int* cmin, int* cmax, const char* word, int len);
struct hentry* compound_check(const char* word,
int len,
struct hentry* compound_check(const std::string& word,
short wordnum,
short numsyllable,
short maxwordnum,
@ -294,47 +287,37 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
hentry** words,
hentry** rwords,
char hu_mov_rule,
char** result,
char* partresult);
std::string& result,
const std::string* partresult);
int get_suffix_words(short unsigned* suff,
std::vector<std::string> get_suffix_words(short unsigned* suff,
int len,
const char* root_word,
char** slst);
const char* root_word);
struct hentry* lookup(const char* word);
int get_numrep() const;
struct replentry* get_reptable() const;
const std::vector<replentry>& get_reptable() const;
RepList* get_iconvtable() const;
RepList* get_oconvtable() const;
struct phonetable* get_phonetable() const;
int get_nummap() const;
struct mapentry* get_maptable() const;
int get_numbreak() const;
char** get_breaktable() const;
char* get_encoding();
const std::vector<mapentry>& get_maptable() const;
const std::vector<std::string>& get_breaktable() const;
const std::string& get_encoding();
int get_langnum() const;
char* get_key_string();
char* get_try_string() const;
const char* get_wordchars() const;
const std::string& get_wordchars() const;
const std::vector<w_char>& get_wordchars_utf16() const;
char* get_ignore() const;
const char* get_ignore() const;
const std::vector<w_char>& get_ignore_utf16() const;
int get_compound() const;
FLAG get_compoundflag() const;
FLAG get_compoundbegin() const;
FLAG get_forbiddenword() const;
FLAG get_nosuggest() const;
FLAG get_nongramsuggest() const;
FLAG get_needaffix() const;
FLAG get_onlyincompound() const;
FLAG get_compoundroot() const;
FLAG get_lemma_present() const;
int get_checknum() const;
const char* get_prefix() const;
const char* get_suffix() const;
const char* get_derived() const;
const char* get_version() const;
const std::string& get_version() const;
int have_contclass() const;
int get_utf8() const;
int get_complexprefixes() const;
@ -355,26 +338,25 @@ class LIBHUNSPELL_DLL_EXPORTED AffixMgr {
private:
int parse_file(const char* affpath, const char* key);
int parse_flag(char* line, unsigned short* out, FileMgr* af);
int parse_num(char* line, int* out, FileMgr* af);
int parse_cpdsyllable(char* line, FileMgr* af);
int parse_reptable(char* line, FileMgr* af);
int parse_convtable(char* line,
bool parse_flag(const std::string& line, unsigned short* out, FileMgr* af);
bool parse_num(const std::string& line, int* out, FileMgr* af);
bool parse_cpdsyllable(const std::string& line, FileMgr* af);
bool parse_reptable(const std::string& line, FileMgr* af);
bool parse_convtable(const std::string& line,
FileMgr* af,
RepList** rl,
const char* keyword);
int parse_phonetable(char* line, FileMgr* af);
int parse_maptable(char* line, FileMgr* af);
int parse_breaktable(char* line, FileMgr* af);
int parse_checkcpdtable(char* line, FileMgr* af);
int parse_defcpdtable(char* line, FileMgr* af);
int parse_affix(char* line, const char at, FileMgr* af, char* dupflags);
const std::string& keyword);
bool parse_phonetable(const std::string& line, FileMgr* af);
bool parse_maptable(const std::string& line, FileMgr* af);
bool parse_breaktable(const std::string& line, FileMgr* af);
bool parse_checkcpdtable(const std::string& line, FileMgr* af);
bool parse_defcpdtable(const std::string& line, FileMgr* af);
bool parse_affix(const std::string& line, const char at, FileMgr* af, char* dupflags);
void reverse_condition(std::string&);
void debugflag(char* result, unsigned short flag);
std::string& debugflag(std::string& result, unsigned short flag);
int condlen(const char*);
int encodeit(affentry& entry, const char* cs);
int encodeit(AffEntry& entry, const char* cs);
int build_pfxtree(PfxEntry* pfxptr);
int build_sfxtree(SfxEntry* sfxptr);
int process_pfx_order();

Просмотреть файл

@ -38,8 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _ATYPES_HXX_
#define _ATYPES_HXX_
#ifndef ATYPES_HXX_
#define ATYPES_HXX_
#ifndef HUNSPELL_WARNING
#include <stdio.h>
@ -55,15 +55,15 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
// HUNSTEM def.
#define HUNSTEM
#include "hashmgr.hxx"
#include "w_char.hxx"
#include <algorithm>
#include <string>
#include <vector>
#define SETSIZE 256
#define CONTSIZE 65536
// affentry options
// AffEntry options
#define aeXPRODUCT (1 << 0)
#define aeUTF8 (1 << 1)
#define aeALIASF (1 << 2)
@ -85,8 +85,6 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
#define SPELL_ORIGCAP (1 << 5)
#define SPELL_WARN (1 << 6)
#define MAXLNLEN 8192
#define MINCPDLEN 3
#define MAXCOMPOUND 10
#define MAXCONDLEN 20
@ -100,46 +98,25 @@ static inline void HUNSPELL_WARNING(FILE*, const char*, ...) {}
#define TESTAFF(a, b, c) (std::binary_search(a, a + c, b))
struct affentry {
std::string strip;
std::string appnd;
char numconds;
char opts;
unsigned short aflag;
unsigned short* contclass;
short contclasslen;
union {
char conds[MAXCONDLEN];
struct {
char conds1[MAXCONDLEN_1];
char* conds2;
} l;
} c;
char* morphcode;
};
struct guessword {
char* word;
bool allow;
char* orig;
};
struct mapentry {
char** set;
int len;
};
struct flagentry {
FLAG* def;
int len;
};
typedef std::vector<std::string> mapentry;
typedef std::vector<FLAG> flagentry;
struct patentry {
char* pattern;
char* pattern2;
char* pattern3;
std::string pattern;
std::string pattern2;
std::string pattern3;
FLAG cond;
FLAG cond2;
patentry()
: cond(FLAG_NULL)
, cond2(FLAG_NULL) {
}
};
#endif

Просмотреть файл

@ -38,18 +38,17 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _BASEAFF_HXX_
#define _BASEAFF_HXX_
#ifndef BASEAFF_HXX_
#define BASEAFF_HXX_
#include "hunvisapi.h"
#include <string>
class LIBHUNSPELL_DLL_EXPORTED AffEntry {
class AffEntry {
private:
AffEntry(const AffEntry&);
AffEntry& operator=(const AffEntry&);
protected:
public:
AffEntry()
: numconds(0),
opts(0),
@ -57,6 +56,7 @@ class LIBHUNSPELL_DLL_EXPORTED AffEntry {
morphcode(0),
contclass(NULL),
contclasslen(0) {}
virtual ~AffEntry();
std::string appnd;
std::string strip;
unsigned char numconds;

Просмотреть файл

@ -76,6 +76,7 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <sstream>
#include "csutil.hxx"
#include "atypes.hxx"
@ -122,26 +123,24 @@ static struct unicode_info2* utf_tbl = NULL;
static int utf_tbl_count =
0; // utf_tbl can be used by multiple Hunspell instances
FILE* myfopen(const char* path, const char* mode) {
#ifdef _WIN32
void myopen(std::ifstream& stream, const char* path, std::ios_base::openmode mode)
{
#if defined(_WIN32) && defined(_MSC_VER)
#define WIN32_LONG_PATH_PREFIX "\\\\?\\"
if (strncmp(path, WIN32_LONG_PATH_PREFIX, 4) == 0) {
int len = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
wchar_t* buff = (wchar_t*)malloc(len * sizeof(wchar_t));
wchar_t* buff2 = (wchar_t*)malloc(len * sizeof(wchar_t));
FILE* f = NULL;
if (buff && buff2) {
MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
if (_wfullpath(buff2, buff, len) != NULL) {
f = _wfopen(buff2, (strcmp(mode, "r") == 0) ? L"r" : L"rb");
}
free(buff);
free(buff2);
wchar_t* buff = new wchar_t[len];
wchar_t* buff2 = new wchar_t[len];
MultiByteToWideChar(CP_UTF8, 0, path, -1, buff, len);
if (_wfullpath(buff2, buff, len) != NULL) {
stream.open(buff2, mode);
}
return f;
delete [] buff;
delete [] buff2;
}
else
#endif
return fopen(path, mode);
stream.open(path, mode);
}
std::string& u16_u8(std::string& dest, const std::vector<w_char>& src) {
@ -218,7 +217,7 @@ int u8_u16(std::vector<w_char>& dest, const std::string& src) {
case 0xd0: { // 2-byte UTF-8 codes
if ((*(u8 + 1) & 0xc0) == 0x80) {
u2.h = (*u8 & 0x1f) >> 2;
u2.l = (*u8 << 6) + (*(u8 + 1) & 0x3f);
u2.l = (static_cast<unsigned char>(*u8) << 6) + (*(u8 + 1) & 0x3f);
++u8;
} else {
HUNSPELL_WARNING(stderr,
@ -275,34 +274,35 @@ int u8_u16(std::vector<w_char>& dest, const std::string& src) {
return dest.size();
}
// strip strings into token based on single char delimiter
// acts like strsep() but only uses a delim char and not
// a delim string
// default delimiter: white space characters
namespace {
class is_any_of {
public:
explicit is_any_of(const std::string& in) : chars(in) {}
char* mystrsep(char** stringp, const char delim) {
char* mp = *stringp;
if (*mp != '\0') {
char* dp;
if (delim) {
dp = strchr(mp, delim);
} else {
// don't use isspace() here, the string can be in some random charset
// that's way different than the locale's
for (dp = mp; (*dp && *dp != ' ' && *dp != '\t'); dp++)
;
if (!*dp)
dp = NULL;
}
if (dp) {
*stringp = dp + 1;
*dp = '\0';
} else {
*stringp = mp + strlen(mp);
}
return mp;
}
return NULL;
bool operator()(char c) { return chars.find(c) != std::string::npos; }
private:
std::string chars;
};
}
std::string::const_iterator mystrsep(const std::string &str,
std::string::const_iterator& start) {
std::string::const_iterator end = str.end();
is_any_of op(" \t");
// don't use isspace() here, the string can be in some random charset
// that's way different than the locale's
std::string::const_iterator sp = start;
while (sp != end && op(*sp))
++sp;
std::string::const_iterator dp = sp;
while (dp != end && !op(*dp))
++dp;
start = dp;
return sp;
}
// replaces strdup with ansi version
@ -320,142 +320,98 @@ char* mystrdup(const char* s) {
return d;
}
// strcat for limited length destination string
char* mystrcat(char* dest, const char* st, int max) {
int len;
int len2;
if (dest == NULL || st == NULL)
return dest;
len = strlen(dest);
len2 = strlen(st);
if (len + len2 + 1 > max)
return dest;
strcpy(dest + len, st);
return dest;
}
// remove cross-platform text line end characters
void mychomp(char* s) {
size_t k = strlen(s);
if ((k > 0) && ((*(s + k - 1) == '\r') || (*(s + k - 1) == '\n')))
*(s + k - 1) = '\0';
if ((k > 1) && (*(s + k - 2) == '\r'))
*(s + k - 2) = '\0';
void mychomp(std::string& s) {
size_t k = s.size();
size_t newsize = k;
if ((k > 0) && ((s[k - 1] == '\r') || (s[k - 1] == '\n')))
--newsize;
if ((k > 1) && (s[k - 2] == '\r'))
--newsize;
s.resize(newsize);
}
// break text to lines
// return number of lines
int line_tok(const char* text, char*** lines, char breakchar) {
int linenum = 0;
if (!text) {
return linenum;
}
char* dup = mystrdup(text);
char* p = strchr(dup, breakchar);
while (p) {
linenum++;
*p = '\0';
p++;
p = strchr(p, breakchar);
}
linenum++;
*lines = (char**)malloc(linenum * sizeof(char*));
if (!(*lines)) {
free(dup);
return 0;
std::vector<std::string> line_tok(const std::string& text, char breakchar) {
std::vector<std::string> ret;
if (text.empty()) {
return ret;
}
p = dup;
int l = 0;
for (int i = 0; i < linenum; i++) {
if (*p != '\0') {
(*lines)[l] = mystrdup(p);
if (!(*lines)[l]) {
for (i = 0; i < l; i++)
free((*lines)[i]);
free(dup);
return 0;
}
l++;
std::stringstream ss(text);
std::string tok;
while(std::getline(ss, tok, breakchar)) {
if (!tok.empty()) {
ret.push_back(tok);
}
p += strlen(p) + 1;
}
free(dup);
if (!l) {
free(*lines);
*lines = NULL;
}
return l;
return ret;
}
// uniq line in place
char* line_uniq(char* text, char breakchar) {
char** lines;
int linenum = line_tok(text, &lines, breakchar);
int i;
strcpy(text, lines[0]);
for (i = 1; i < linenum; i++) {
int dup = 0;
for (int j = 0; j < i; j++) {
if (strcmp(lines[i], lines[j]) == 0) {
dup = 1;
void line_uniq(std::string& text, char breakchar)
{
std::vector<std::string> lines = line_tok(text, breakchar);
text.clear();
if (lines.empty()) {
return;
}
text = lines[0];
for (size_t i = 1; i < lines.size(); ++i) {
bool dup = false;
for (size_t j = 0; j < i; ++j) {
if (lines[i] == lines[j]) {
dup = true;
break;
}
}
if (!dup) {
if ((i > 1) || (*(lines[0]) != '\0')) {
sprintf(text + strlen(text), "%c", breakchar);
}
strcat(text, lines[i]);
if (!text.empty())
text.push_back(breakchar);
text.append(lines[i]);
}
}
for (i = 0; i < linenum; i++) {
free(lines[i]);
}
free(lines);
return text;
}
// uniq and boundary for compound analysis: "1\n\2\n\1" -> " ( \1 | \2 ) "
char* line_uniq_app(char** text, char breakchar) {
if (!strchr(*text, breakchar)) {
return *text;
void line_uniq_app(std::string& text, char breakchar) {
if (text.find(breakchar) == std::string::npos) {
return;
}
char** lines;
int i;
int linenum = line_tok(*text, &lines, breakchar);
int dup = 0;
for (i = 0; i < linenum; i++) {
for (int j = 0; j < (i - 1); j++) {
if (strcmp(lines[i], lines[j]) == 0) {
*(lines[i]) = '\0';
dup++;
std::vector<std::string> lines = line_tok(text, breakchar);
text.clear();
if (lines.empty()) {
return;
}
text = lines[0];
for (size_t i = 1; i < lines.size(); ++i) {
bool dup = false;
for (size_t j = 0; j < i; ++j) {
if (lines[i] == lines[j]) {
dup = true;
break;
}
}
}
if ((linenum - dup) == 1) {
strcpy(*text, lines[0]);
freelist(&lines, linenum);
return *text;
}
char* newtext = (char*)malloc(strlen(*text) + 2 * linenum + 3 + 1);
if (newtext) {
free(*text);
*text = newtext;
} else {
freelist(&lines, linenum);
return *text;
}
strcpy(*text, " ( ");
for (i = 0; i < linenum; i++)
if (*(lines[i])) {
sprintf(*text + strlen(*text), "%s%s", lines[i], " | ");
if (!dup) {
if (!text.empty())
text.push_back(breakchar);
text.append(lines[i]);
}
(*text)[strlen(*text) - 2] = ')'; // " ) "
freelist(&lines, linenum);
return *text;
}
if (lines.size() == 1) {
text = lines[0];
return;
}
text.assign(" ( ");
for (size_t i = 0; i < lines.size(); ++i) {
text.append(lines[i]);
text.append(" | ");
}
text[text.size() - 2] = ')'; // " ) "
}
// append s to ends of every lines in text
@ -469,111 +425,6 @@ std::string& strlinecat(std::string& str, const std::string& apd) {
return str;
}
// morphcmp(): compare MORPH_DERI_SFX, MORPH_INFL_SFX and MORPH_TERM_SFX fields
// in the first line of the inputs
// return 0, if inputs equal
// return 1, if inputs may equal with a secondary suffix
// otherwise return -1
int morphcmp(const char* s, const char* t) {
int se = 0;
int te = 0;
const char* sl;
const char* tl;
const char* olds;
const char* oldt;
if (!s || !t)
return 1;
olds = s;
sl = strchr(s, '\n');
s = strstr(s, MORPH_DERI_SFX);
if (!s || (sl && sl < s))
s = strstr(olds, MORPH_INFL_SFX);
if (!s || (sl && sl < s)) {
s = strstr(olds, MORPH_TERM_SFX);
olds = NULL;
}
oldt = t;
tl = strchr(t, '\n');
t = strstr(t, MORPH_DERI_SFX);
if (!t || (tl && tl < t))
t = strstr(oldt, MORPH_INFL_SFX);
if (!t || (tl && tl < t)) {
t = strstr(oldt, MORPH_TERM_SFX);
oldt = NULL;
}
while (s && t && (!sl || sl > s) && (!tl || tl > t)) {
s += MORPH_TAG_LEN;
t += MORPH_TAG_LEN;
se = 0;
te = 0;
while ((*s == *t) && !se && !te) {
s++;
t++;
switch (*s) {
case ' ':
case '\n':
case '\t':
case '\0':
se = 1;
}
switch (*t) {
case ' ':
case '\n':
case '\t':
case '\0':
te = 1;
}
}
if (!se || !te) {
// not terminal suffix difference
if (olds)
return -1;
return 1;
}
olds = s;
s = strstr(s, MORPH_DERI_SFX);
if (!s || (sl && sl < s))
s = strstr(olds, MORPH_INFL_SFX);
if (!s || (sl && sl < s)) {
s = strstr(olds, MORPH_TERM_SFX);
olds = NULL;
}
oldt = t;
t = strstr(t, MORPH_DERI_SFX);
if (!t || (tl && tl < t))
t = strstr(oldt, MORPH_INFL_SFX);
if (!t || (tl && tl < t)) {
t = strstr(oldt, MORPH_TERM_SFX);
oldt = NULL;
}
}
if (!s && !t && se && te)
return 0;
return 1;
}
int get_sfxcount(const char* morph) {
if (!morph || !*morph)
return 0;
int n = 0;
const char* old = morph;
morph = strstr(morph, MORPH_DERI_SFX);
if (!morph)
morph = strstr(old, MORPH_INFL_SFX);
if (!morph)
morph = strstr(old, MORPH_TERM_SFX);
while (morph) {
n++;
old = morph;
morph = strstr(morph + 1, MORPH_DERI_SFX);
if (!morph)
morph = strstr(old + 1, MORPH_INFL_SFX);
if (!morph)
morph = strstr(old + 1, MORPH_TERM_SFX);
}
return n;
}
int fieldlen(const char* r) {
int n = 0;
while (r && *r != ' ' && *r != '\t' && *r != '\0' && *r != '\n') {
@ -615,33 +466,6 @@ std::string& mystrrep(std::string& str,
return str;
}
char* mystrrep(char* word, const char* pat, const char* rep) {
char* pos = strstr(word, pat);
if (pos) {
int replen = strlen(rep);
int patlen = strlen(pat);
while (pos) {
if (replen < patlen) {
char* end = word + strlen(word);
char* next = pos + replen;
char* prev = pos + strlen(pat);
for (; prev < end;* next = *prev, prev++, next++)
;
*next = '\0';
} else if (replen > patlen) {
char* end = pos + patlen;
char* next = word + strlen(word) + replen - patlen;
char* prev = next - replen + patlen;
for (; prev >= end;* next = *prev, prev--, next--)
;
}
strncpy(pos, rep, replen);
pos = strstr(word, pat);
}
}
return word;
}
// reverse word
size_t reverseword(std::string& word) {
std::reverse(word.begin(), word.end());
@ -657,35 +481,19 @@ size_t reverseword_utf(std::string& word) {
return w.size();
}
int uniqlist(char** list, int n) {
int i;
if (n < 2)
return n;
for (i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (list[j] && list[i] && (strcmp(list[j], list[i]) == 0)) {
free(list[i]);
list[i] = NULL;
break;
}
}
}
int m = 1;
for (i = 1; i < n; i++)
if (list[i]) {
list[m] = list[i];
m++;
}
return m;
}
void uniqlist(std::vector<std::string>& list) {
if (list.size() < 2)
return;
void freelist(char*** list, int n) {
if (list && *list) {
for (int i = 0; i < n; i++)
free((*list)[i]);
free(*list);
*list = NULL;
std::vector<std::string> ret;
ret.push_back(list[0]);
for (size_t i = 1; i < list.size(); ++i) {
if (std::find(ret.begin(), ret.end(), list[i]) == ret.end())
ret.push_back(list[i]);
}
list.swap(ret);
}
namespace {
@ -2457,9 +2265,9 @@ static void toAsciiLowerAndRemoveNonAlphanumeric(const char* pName,
*pBuf = '\0';
}
struct cs_info* get_current_cs(const char* es) {
char* normalized_encoding = new char[strlen(es) + 1];
toAsciiLowerAndRemoveNonAlphanumeric(es, normalized_encoding);
struct cs_info* get_current_cs(const std::string& es) {
char* normalized_encoding = new char[es.size() + 1];
toAsciiLowerAndRemoveNonAlphanumeric(es.c_str(), normalized_encoding);
struct cs_info* ccs = NULL;
int n = sizeof(encds) / sizeof(encds[0]);
@ -2474,7 +2282,7 @@ struct cs_info* get_current_cs(const char* es) {
if (!ccs) {
HUNSPELL_WARNING(stderr,
"error: unknown encoding %s: using %s as fallback\n", es,
"error: unknown encoding %s: using %s as fallback\n", es.c_str(),
encds[0].enc_name);
ccs = encds[0].cs_table;
}
@ -2485,7 +2293,7 @@ struct cs_info* get_current_cs(const char* es) {
// XXX This function was rewritten for mozilla. Instead of storing the
// conversion tables static in this file, create them when needed
// with help the mozilla backend.
struct cs_info* get_current_cs(const char* es) {
struct cs_info* get_current_cs(const std::string& es) {
struct cs_info* ccs = new cs_info[256];
// Initialze the array with dummy data so that we wouldn't need
// to return null in case of failures.
@ -2500,7 +2308,7 @@ struct cs_info* get_current_cs(const char* es) {
nsresult rv;
nsAutoCString label(es);
nsAutoCString label(es.c_str());
nsAutoCString encoding;
if (!EncodingUtils::FindEncodingForLabelNoReplacement(label, encoding)) {
return ccs;
@ -2565,21 +2373,18 @@ struct cs_info* get_current_cs(const char* es) {
#endif
// primitive isalpha() replacement for tokenization
char* get_casechars(const char* enc) {
std::string get_casechars(const char* enc) {
struct cs_info* csconv = get_current_cs(enc);
char expw[MAXLNLEN];
char* p = expw;
for (int i = 0; i <= 255; i++) {
std::string expw;
for (int i = 0; i <= 255; ++i) {
if (cupper(csconv, i) != clower(csconv, i)) {
*p = static_cast<char>(i);
p++;
expw.push_back(static_cast<char>(i));
}
}
*p = '\0';
#ifdef MOZILLA_CLIENT
delete[] csconv;
#endif
return mystrdup(expw);
return expw;
}
// language to encoding default map
@ -2606,10 +2411,10 @@ static struct lang_map lang2enc[] =
{"tr_TR", LANG_tr}, // for back-compatibility
{"ru", LANG_ru}, {"uk", LANG_uk}};
int get_lang_num(const char* lang) {
int get_lang_num(const std::string& lang) {
int n = sizeof(lang2enc) / sizeof(lang2enc[0]);
for (int i = 0; i < n; i++) {
if (strcmp(lang, lang2enc[i].lang) == 0) {
if (strcmp(lang.c_str(), lang2enc[i].lang) == 0) {
return lang2enc[i].num;
}
}
@ -2618,26 +2423,21 @@ int get_lang_num(const char* lang) {
#ifndef OPENOFFICEORG
#ifndef MOZILLA_CLIENT
int initialize_utf_tbl() {
void initialize_utf_tbl() {
utf_tbl_count++;
if (utf_tbl)
return 0;
utf_tbl = (unicode_info2*)malloc(CONTSIZE * sizeof(unicode_info2));
if (utf_tbl) {
size_t j;
for (j = 0; j < CONTSIZE; j++) {
utf_tbl[j].cletter = 0;
utf_tbl[j].clower = (unsigned short)j;
utf_tbl[j].cupper = (unsigned short)j;
}
for (j = 0; j < UTF_LST_LEN; j++) {
utf_tbl[utf_lst[j].c].cletter = 1;
utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
}
} else
return 1;
return 0;
return;
utf_tbl = new unicode_info2[CONTSIZE];
for (size_t j = 0; j < CONTSIZE; ++j) {
utf_tbl[j].cletter = 0;
utf_tbl[j].clower = (unsigned short)j;
utf_tbl[j].cupper = (unsigned short)j;
}
for (size_t j = 0; j < UTF_LST_LEN; ++j) {
utf_tbl[utf_lst[j].c].cletter = 1;
utf_tbl[utf_lst[j].c].clower = utf_lst[j].clower;
utf_tbl[utf_lst[j].c].cupper = utf_lst[j].cupper;
}
}
#endif
#endif
@ -2646,7 +2446,7 @@ void free_utf_tbl() {
if (utf_tbl_count > 0)
utf_tbl_count--;
if (utf_tbl && (utf_tbl_count == 0)) {
free(utf_tbl);
delete[] utf_tbl;
utf_tbl = NULL;
}
}
@ -2775,18 +2575,6 @@ size_t remove_ignored_chars_utf(std::string& word,
return w2.size();
}
namespace {
class is_any_of {
public:
is_any_of(const std::string& in) : chars(in) {}
bool operator()(char c) { return chars.find(c) != std::string::npos; }
private:
std::string chars;
};
}
// strip all ignored characters in the string
size_t remove_ignored_chars(std::string& word,
const std::string& ignored_chars) {
@ -2796,54 +2584,48 @@ size_t remove_ignored_chars(std::string& word,
return word.size();
}
int parse_string(char* line, char** out, int ln) {
char* tp = line;
char* piece;
bool parse_string(const std::string& line, std::string& out, int ln) {
if (!out.empty()) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
return false;
}
int i = 0;
int np = 0;
if (*out) {
HUNSPELL_WARNING(stderr, "error: line %d: multiple definitions\n", ln);
return 1;
}
piece = mystrsep(&tp, 0);
while (piece) {
if (*piece != '\0') {
switch (i) {
case 0: {
np++;
break;
}
case 1: {
*out = mystrdup(piece);
if (!*out)
return 1;
np++;
break;
}
default:
break;
std::string::const_iterator iter = line.begin();
std::string::const_iterator start_piece = mystrsep(line, iter);
while (start_piece != line.end()) {
switch (i) {
case 0: {
np++;
break;
}
i++;
case 1: {
out.assign(start_piece, iter);
np++;
break;
}
default:
break;
}
// free(piece);
piece = mystrsep(&tp, 0);
++i;
start_piece = mystrsep(line, iter);
}
if (np != 2) {
HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", ln);
return 1;
return false;
}
return 0;
return true;
}
bool parse_array(char* line,
char** out,
bool parse_array(const std::string& line,
std::string& out,
std::vector<w_char>& out_utf16,
int utf8,
int ln) {
if (parse_string(line, out, ln))
if (!parse_string(line, out, ln))
return false;
if (utf8) {
u8_u16(out_utf16, *out);
u8_u16(out_utf16, out);
std::sort(out_utf16.begin(), out_utf16.end());
}
return true;

Просмотреть файл

@ -71,13 +71,14 @@
* SUCH DAMAGE.
*/
#ifndef __CSUTILHXX__
#define __CSUTILHXX__
#ifndef CSUTIL_HXX_
#define CSUTIL_HXX_
#include "hunvisapi.h"
// First some base level utility routines
#include <fstream>
#include <string>
#include <vector>
#include <string.h>
@ -127,8 +128,9 @@
#define FORBIDDENWORD 65510
#define ONLYUPCASEFLAG 65511
// fopen or optional _wfopen to fix long pathname problem of WIN32
LIBHUNSPELL_DLL_EXPORTED FILE* myfopen(const char* path, const char* mode);
// fix long pathname problem of WIN32 by using w_char std::fstream::open override
LIBHUNSPELL_DLL_EXPORTED void myopen(std::ifstream& stream, const char* path,
std::ios_base::openmode mode);
// convert UTF-16 characters to UTF-8
LIBHUNSPELL_DLL_EXPORTED std::string& u16_u8(std::string& dest,
@ -139,21 +141,16 @@ LIBHUNSPELL_DLL_EXPORTED int u8_u16(std::vector<w_char>& dest,
const std::string& src);
// remove end of line char(s)
LIBHUNSPELL_DLL_EXPORTED void mychomp(char* s);
LIBHUNSPELL_DLL_EXPORTED void mychomp(std::string& s);
// duplicate string
LIBHUNSPELL_DLL_EXPORTED char* mystrdup(const char* s);
// strcat for limited length destination string
LIBHUNSPELL_DLL_EXPORTED char* mystrcat(char* dest, const char* st, int max);
// parse into tokens with char delimiter
LIBHUNSPELL_DLL_EXPORTED char* mystrsep(char** sptr, const char delim);
LIBHUNSPELL_DLL_EXPORTED std::string::const_iterator mystrsep(const std::string &str,
std::string::const_iterator& start);
// replace pat by rep in word and return word
LIBHUNSPELL_DLL_EXPORTED char* mystrrep(char* word,
const char* pat,
const char* rep);
LIBHUNSPELL_DLL_EXPORTED std::string& mystrrep(std::string& str,
const std::string& search,
const std::string& replace);
@ -163,13 +160,13 @@ LIBHUNSPELL_DLL_EXPORTED std::string& strlinecat(std::string& str,
const std::string& apd);
// tokenize into lines with new line
LIBHUNSPELL_DLL_EXPORTED int line_tok(const char* text,
char*** lines,
char breakchar);
LIBHUNSPELL_DLL_EXPORTED std::vector<std::string> line_tok(const std::string& text,
char breakchar);
// tokenize into lines with new line and uniq in place
LIBHUNSPELL_DLL_EXPORTED char* line_uniq(char* text, char breakchar);
LIBHUNSPELL_DLL_EXPORTED char* line_uniq_app(char** text, char breakchar);
LIBHUNSPELL_DLL_EXPORTED void line_uniq(std::string& text, char breakchar);
LIBHUNSPELL_DLL_EXPORTED void line_uniq_app(std::string& text, char breakchar);
// reverse word
LIBHUNSPELL_DLL_EXPORTED size_t reverseword(std::string& word);
@ -178,10 +175,7 @@ LIBHUNSPELL_DLL_EXPORTED size_t reverseword(std::string& word);
LIBHUNSPELL_DLL_EXPORTED size_t reverseword_utf(std::string&);
// remove duplicates
LIBHUNSPELL_DLL_EXPORTED int uniqlist(char** list, int n);
// free character array list
LIBHUNSPELL_DLL_EXPORTED void freelist(char*** list, int n);
LIBHUNSPELL_DLL_EXPORTED void uniqlist(std::vector<std::string>& list);
// character encoding information
struct cs_info {
@ -190,7 +184,7 @@ struct cs_info {
unsigned char cupper;
};
LIBHUNSPELL_DLL_EXPORTED int initialize_utf_tbl();
LIBHUNSPELL_DLL_EXPORTED void initialize_utf_tbl();
LIBHUNSPELL_DLL_EXPORTED void free_utf_tbl();
LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetoupper(unsigned short c,
int langnum);
@ -200,13 +194,13 @@ LIBHUNSPELL_DLL_EXPORTED unsigned short unicodetolower(unsigned short c,
int langnum);
LIBHUNSPELL_DLL_EXPORTED int unicodeisalpha(unsigned short c);
LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const char* es);
LIBHUNSPELL_DLL_EXPORTED struct cs_info* get_current_cs(const std::string& es);
// get language identifiers of language codes
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const char* lang);
LIBHUNSPELL_DLL_EXPORTED int get_lang_num(const std::string& lang);
// get characters of the given 8bit encoding with lower- and uppercase forms
LIBHUNSPELL_DLL_EXPORTED char* get_casechars(const char* enc);
LIBHUNSPELL_DLL_EXPORTED std::string get_casechars(const char* enc);
// convert std::string to all caps
LIBHUNSPELL_DLL_EXPORTED std::string& mkallcap(std::string& s,
@ -256,10 +250,12 @@ LIBHUNSPELL_DLL_EXPORTED size_t remove_ignored_chars(
std::string& word,
const std::string& ignored_chars);
LIBHUNSPELL_DLL_EXPORTED int parse_string(char* line, char** out, int ln);
LIBHUNSPELL_DLL_EXPORTED bool parse_string(const std::string& line,
std::string& out,
int ln);
LIBHUNSPELL_DLL_EXPORTED bool parse_array(char* line,
char** out,
LIBHUNSPELL_DLL_EXPORTED bool parse_array(const std::string& line,
std::string& out,
std::vector<w_char>& out_utf16,
int utf8,
int ln);
@ -270,10 +266,6 @@ LIBHUNSPELL_DLL_EXPORTED bool copy_field(std::string& dest,
const std::string& morph,
const std::string& var);
LIBHUNSPELL_DLL_EXPORTED int morphcmp(const char* s, const char* t);
LIBHUNSPELL_DLL_EXPORTED int get_sfxcount(const char* morph);
// conversion function for protected memory
LIBHUNSPELL_DLL_EXPORTED void store_pointer(char* dest, char* source);

Просмотреть файл

@ -86,33 +86,33 @@ int FileMgr::fail(const char* err, const char* par) {
FileMgr::FileMgr(const char* file, const char* key) : hin(NULL), linenum(0) {
in[0] = '\0';
fin = myfopen(file, "r");
if (!fin) {
myopen(fin, file, std::ios_base::in);
if (!fin.is_open()) {
// check hzipped file
std::string st(file);
st.append(HZIP_EXTENSION);
hin = new Hunzip(st.c_str(), key);
}
if (!fin && !hin)
if (!fin.is_open() && !hin->is_open())
fail(MSG_OPEN, file);
}
FileMgr::~FileMgr() {
if (fin)
fclose(fin);
if (hin)
delete hin;
delete hin;
}
char* FileMgr::getline() {
const char* l;
linenum++;
if (fin)
return fgets(in, BUFSIZE - 1, fin);
if (hin && ((l = hin->getline()) != NULL))
return strcpy(in, l);
linenum--;
return NULL;
bool FileMgr::getline(std::string& dest) {
bool ret = false;
++linenum;
if (fin.is_open()) {
ret = static_cast<bool>(std::getline(fin, dest));
} else if (hin->is_open()) {
ret = hin->getline(dest);
}
if (!ret) {
--linenum;
}
return ret;
}
int FileMgr::getlinenum() {

Просмотреть файл

@ -72,21 +72,21 @@
*/
/* file manager class - read lines of files [filename] OR [filename.hz] */
#ifndef _FILEMGR_HXX_
#define _FILEMGR_HXX_
#include "hunvisapi.h"
#ifndef FILEMGR_HXX_
#define FILEMGR_HXX_
#include "hunzip.hxx"
#include <stdio.h>
#include <string>
#include <fstream>
class LIBHUNSPELL_DLL_EXPORTED FileMgr {
class FileMgr {
private:
FileMgr(const FileMgr&);
FileMgr& operator=(const FileMgr&);
protected:
FILE* fin;
std::ifstream fin;
Hunzip* hin;
char in[BUFSIZE + 50]; // input buffer
int fail(const char* err, const char* par);
@ -95,7 +95,7 @@ class LIBHUNSPELL_DLL_EXPORTED FileMgr {
public:
FileMgr(const char* filename, const char* key = NULL);
~FileMgr();
char* getline();
bool getline(std::string&);
int getlinenum();
};
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -71,10 +71,8 @@
* SUCH DAMAGE.
*/
#ifndef _HASHMGR_HXX_
#define _HASHMGR_HXX_
#include "hunvisapi.h"
#ifndef HASHMGR_HXX_
#define HASHMGR_HXX_
#include <stdio.h>
#include <string>
@ -86,7 +84,7 @@
enum flag { FLAG_CHAR, FLAG_LONG, FLAG_NUM, FLAG_UNI };
class LIBHUNSPELL_DLL_EXPORTED HashMgr {
class HashMgr {
int tablesize;
struct hentry** tableptr;
flag flag_mode;
@ -94,10 +92,10 @@ class LIBHUNSPELL_DLL_EXPORTED HashMgr {
int utf8;
unsigned short forbiddenword;
int langnum;
char* enc;
char* lang;
std::string enc;
std::string lang;
struct cs_info* csconv;
char* ignorechars;
std::string ignorechars;
std::vector<w_char> ignorechars_utf16;
int numaliasf; // flag vector `compression' with aliases
unsigned short** aliasf;
@ -114,35 +112,35 @@ class LIBHUNSPELL_DLL_EXPORTED HashMgr {
struct hentry* walk_hashtable(int& col, struct hentry* hp) const;
int add(const std::string& word);
int add_with_affix(const char* word, const char* pattern);
int remove(const char* word);
int decode_flags(unsigned short** result, char* flags, FileMgr* af);
unsigned short decode_flag(const char* flag);
char* encode_flag(unsigned short flag);
int is_aliasf();
int get_aliasf(int index, unsigned short** fvec, FileMgr* af);
int is_aliasm();
char* get_aliasm(int index);
int add_with_affix(const std::string& word, const std::string& pattern);
int remove(const std::string& word);
int decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const;
bool decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const;
unsigned short decode_flag(const char* flag) const;
char* encode_flag(unsigned short flag) const;
int is_aliasf() const;
int get_aliasf(int index, unsigned short** fvec, FileMgr* af) const;
int is_aliasm() const;
char* get_aliasm(int index) const;
private:
int get_clen_and_captype(const std::string& word, int* captype);
int load_tables(const char* tpath, const char* key);
int add_word(const char* word,
int wbl,
int add_word(const std::string& word,
int wcl,
unsigned short* ap,
int al,
const char* desc,
const std::string* desc,
bool onlyupcase);
int load_config(const char* affpath, const char* key);
int parse_aliasf(char* line, FileMgr* af);
bool parse_aliasf(const std::string& line, FileMgr* af);
int add_hidden_capitalized_word(const std::string& word,
int wcl,
unsigned short* flags,
int al,
char* dp,
const std::string* dp,
int captype);
int parse_aliasm(char* line, FileMgr* af);
bool parse_aliasm(const std::string& line, FileMgr* af);
int remove_forbidden_flag(const std::string& word);
};

Просмотреть файл

@ -38,8 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _HTYPES_HXX_
#define _HTYPES_HXX_
#ifndef HTYPES_HXX_
#define HTYPES_HXX_
#define ROTATE_LEN 5

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -38,8 +38,8 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _MYSPELLMGR_H_
#define _MYSPELLMGR_H_
#ifndef MYSPELLMGR_H_
#define MYSPELLMGR_H_
#include "hunvisapi.h"

Просмотреть файл

@ -70,26 +70,30 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef MYSPELLMGR_HXX_
#define MYSPELLMGR_HXX_
#include "hunvisapi.h"
#include "hashmgr.hxx"
#include "affixmgr.hxx"
#include "suggestmgr.hxx"
#include "langnum.hxx"
#include "w_char.hxx"
#include "atypes.hxx"
#include <string>
#include <vector>
#define SPELL_XML "<?xml?>"
#define MAXDIC 20
#define MAXSUGGESTION 15
#define MAXSHARPS 5
#define MAXWORDLEN 176
#define HUNSPELL_OK (1 << 0)
#define HUNSPELL_OK_WARN (1 << 1)
#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)
# define H_DEPRECATED __attribute__((__deprecated__))
#elif defined(_MSC_VER) && (_MSC_VER >= 1300)
# define H_DEPRECATED __declspec(deprecated)
#else
# define H_DEPRECATED
#endif
#ifndef _MYSPELLMGR_HXX_
#define _MYSPELLMGR_HXX_
class HunspellImpl;
class LIBHUNSPELL_DLL_EXPORTED Hunspell {
private:
@ -97,17 +101,7 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
Hunspell& operator=(const Hunspell&);
private:
AffixMgr* pAMgr;
HashMgr* pHMgr[MAXDIC];
int maxdic;
SuggestMgr* pSMgr;
char* affixpath;
char* encoding;
struct cs_info* csconv;
int langnum;
int utf8;
int complexprefixes;
char** wordbreak;
HunspellImpl* m_Impl;
public:
/* Hunspell(aff, dic) - constructor of Hunspell class
@ -118,7 +112,6 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
* long path names (without the long path prefix Hunspell will use fopen()
* with system-dependent character encoding instead of _wfopen()).
*/
Hunspell(const char* affpath, const char* dpath, const char* key = NULL);
~Hunspell();
@ -126,7 +119,7 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
int add_dic(const char* dpath, const char* key = NULL);
/* spell(word) - spellcheck word
* output: 0 = bad word, not 0 = good word
* output: false = bad word, true = good word
*
* plus output:
* info: information bit array, fields:
@ -134,8 +127,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
* SPELL_FORBIDDEN = an explicit forbidden word
* root: root (stem), when input is a word with affix(es)
*/
int spell(const char* word, int* info = NULL, char** root = NULL);
bool spell(const std::string& word, int* info = NULL, std::string* root = NULL);
H_DEPRECATED int spell(const char* word, int* info = NULL, char** root = NULL);
/* suggest(suggestions, word) - search suggestions
* input: pointer to an array of strings pointer and the (bad) word
@ -144,8 +137,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
* a newly allocated array of strings (*slts will be NULL when number
* of suggestion equals 0.)
*/
int suggest(char*** slst, const char* word);
std::vector<std::string> suggest(const std::string& word);
H_DEPRECATED int suggest(char*** slst, const char* word);
/* Suggest words from suffix rules
* suffix_suggest(suggestions, root_word)
@ -155,36 +148,37 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
* a newly allocated array of strings (*slts will be NULL when number
* of suggestion equals 0.)
*/
int suffix_suggest(char*** slst, const char* root_word);
std::vector<std::string> suffix_suggest(const std::string& root_word);
H_DEPRECATED int suffix_suggest(char*** slst, const char* root_word);
/* deallocate suggestion lists */
H_DEPRECATED void free_list(char*** slst, int n);
void free_list(char*** slst, int n);
const std::string& get_dict_encoding() const;
char* get_dic_encoding();
/* morphological functions */
/* analyze(result, word) - morphological analysis of the word */
std::vector<std::string> analyze(const std::string& word);
H_DEPRECATED int analyze(char*** slst, const char* word);
int analyze(char*** slst, const char* word);
/* stem(word) - stemmer function */
std::vector<std::string> stem(const std::string& word);
H_DEPRECATED int stem(char*** slst, const char* word);
/* stem(result, word) - stemmer function */
int stem(char*** slst, const char* word);
/* stem(result, analysis, n) - get stems from a morph. analysis
/* stem(analysis, n) - get stems from a morph. analysis
* example:
* char ** result, result2;
* int n1 = analyze(&result, "words");
* int n2 = stem(&result2, result, n1);
*/
int stem(char*** slst, char** morph, int n);
std::vector<std::string> stem(const std::vector<std::string>& morph);
H_DEPRECATED int stem(char*** slst, char** morph, int n);
/* generate(result, word, word2) - morphological generation by example(s) */
int generate(char*** slst, const char* word, const char* word2);
std::vector<std::string> generate(const std::string& word, const std::string& word2);
H_DEPRECATED int generate(char*** slst, const char* word, const char* word2);
/* generate(result, word, desc, n) - generation by morph. description(s)
* example:
@ -193,66 +187,43 @@ class LIBHUNSPELL_DLL_EXPORTED Hunspell {
* int n = generate(&result, "word", &affix, 1);
* for (int i = 0; i < n; i++) printf("%s\n", result[i]);
*/
int generate(char*** slst, const char* word, char** desc, int n);
std::vector<std::string> generate(const std::string& word, const std::vector<std::string>& pl);
H_DEPRECATED int generate(char*** slst, const char* word, char** desc, int n);
/* functions for run-time modification of the dictionary */
/* add word to the run-time dictionary */
int add(const char* word);
int add(const std::string& word);
/* add word to the run-time dictionary with affix flags of
* the example (a dictionary word): Hunspell will recognize
* affixed forms of the new word, too.
*/
int add_with_affix(const char* word, const char* example);
int add_with_affix(const std::string& word, const std::string& example);
/* remove word from the run-time dictionary */
int remove(const char* word);
int remove(const std::string& word);
/* other */
/* get extra word characters definied in affix file for tokenization */
const char* get_wordchars();
const std::vector<w_char>& get_wordchars_utf16();
const char* get_wordchars() const;
const std::string& get_wordchars_cpp() const;
const std::vector<w_char>& get_wordchars_utf16() const;
struct cs_info* get_csconv();
const char* get_version();
const char* get_version() const;
const std::string& get_version_cpp() const;
int get_langnum() const;
/* need for putdic */
int input_conv(const char* word, char* dest, size_t destsize);
private:
void cleanword(std::string& dest, const char*, int* pcaptype, int* pabbrev);
size_t cleanword2(std::string& dest,
std::vector<w_char>& dest_u,
const char*,
int* w_len,
int* pcaptype,
size_t* pabbrev);
void mkinitcap(std::string& u8);
int mkinitcap2(std::string& u8, std::vector<w_char>& u16);
int mkinitsmall2(std::string& u8, std::vector<w_char>& u16);
void mkallcap(std::string& u8);
int mkallsmall2(std::string& u8, std::vector<w_char>& u16);
struct hentry* checkword(const char*, int* info, char** root);
std::string sharps_u8_l1(const std::string& source);
hentry*
spellsharps(std::string& base, size_t start_pos, int, int, int* info, char** root);
int is_keepcase(const hentry* rv);
int insert_sug(char*** slst, const char* word, int ns);
void cat_result(std::string& result, char* st);
char* stem_description(const char* desc);
int spellml(char*** slst, const char* word);
std::string get_xml_par(const char* par);
const char* get_xml_pos(const char* s, const char* attr);
int get_xml_list(char*** slst, const char* list, const char* tag);
int check_xml_par(const char* q, const char* attr, const char* value);
bool input_conv(const std::string& word, std::string& dest);
H_DEPRECATED int input_conv(const char* word, char* dest, size_t destsize);
};
#endif

Просмотреть файл

@ -1,5 +1,5 @@
#ifndef _HUNSPELL_VISIBILITY_H_
#define _HUNSPELL_VISIBILITY_H_
#ifndef HUNSPELL_VISIBILITY_H_
#define HUNSPELL_VISIBILITY_H_
#if defined(HUNSPELL_STATIC)
# define LIBHUNSPELL_DLL_EXPORTED

Просмотреть файл

@ -59,7 +59,7 @@ int Hunzip::fail(const char* err, const char* par) {
}
Hunzip::Hunzip(const char* file, const char* key)
: fin(NULL), bufsiz(0), lastbit(0), inc(0), inbits(0), outc(0), dec(NULL) {
: bufsiz(0), lastbit(0), inc(0), inbits(0), outc(0) {
in[0] = out[0] = line[0] = '\0';
filename = mystrdup(file);
if (getcode(key) == -1)
@ -70,19 +70,19 @@ Hunzip::Hunzip(const char* file, const char* key)
int Hunzip::getcode(const char* key) {
unsigned char c[2];
int i, j, n, p;
int i, j, n;
int allocatedbit = BASEBITREC;
const char* enc = key;
if (!filename)
return -1;
fin = myfopen(filename, "rb");
if (!fin)
myopen(fin, filename, std::ios_base::in | std::ios_base::binary);
if (!fin.is_open())
return -1;
// read magic number
if ((fread(in, 1, 3, fin) < MAGICLEN) ||
if (!fin.read(in, 3) ||
!(strncmp(MAGIC, in, MAGICLEN) == 0 ||
strncmp(MAGIC_ENCRYPT, in, MAGICLEN) == 0)) {
return fail(MSG_FORMAT, filename);
@ -93,7 +93,7 @@ int Hunzip::getcode(const char* key) {
unsigned char cs;
if (!key)
return fail(MSG_KEY, filename);
if (fread(&c, 1, 1, fin) < 1)
if (!fin.read(reinterpret_cast<char*>(c), 1))
return fail(MSG_FORMAT, filename);
for (cs = 0; *enc; enc++)
cs ^= *enc;
@ -104,7 +104,7 @@ int Hunzip::getcode(const char* key) {
key = NULL;
// read record count
if (fread(&c, 1, 2, fin) < 2)
if (!fin.read(reinterpret_cast<char*>(c), 2))
return fail(MSG_FORMAT, filename);
if (key) {
@ -115,16 +115,14 @@ int Hunzip::getcode(const char* key) {
}
n = ((int)c[0] << 8) + c[1];
dec = (struct bit*)malloc(BASEBITREC * sizeof(struct bit));
if (!dec)
return fail(MSG_MEMORY, filename);
dec.resize(BASEBITREC);
dec[0].v[0] = 0;
dec[0].v[1] = 0;
// read codes
for (i = 0; i < n; i++) {
unsigned char l;
if (fread(c, 1, 2, fin) < 2)
if (!fin.read(reinterpret_cast<char*>(c), 2))
return fail(MSG_FORMAT, filename);
if (key) {
if (*(++enc) == '\0')
@ -134,14 +132,14 @@ int Hunzip::getcode(const char* key) {
enc = key;
c[1] ^= *enc;
}
if (fread(&l, 1, 1, fin) < 1)
if (!fin.read(reinterpret_cast<char*>(&l), 1))
return fail(MSG_FORMAT, filename);
if (key) {
if (*(++enc) == '\0')
enc = key;
l ^= *enc;
}
if (fread(in, 1, l / 8 + 1, fin) < (size_t)l / 8 + 1)
if (!fin.read(in, l / 8 + 1))
return fail(MSG_FORMAT, filename);
if (key)
for (j = 0; j <= l / 8; j++) {
@ -149,7 +147,7 @@ int Hunzip::getcode(const char* key) {
enc = key;
in[j] ^= *enc;
}
p = 0;
int p = 0;
for (j = 0; j < l; j++) {
int b = (in[j / 8] & (1 << (7 - (j % 8)))) ? 1 : 0;
int oldp = p;
@ -158,7 +156,7 @@ int Hunzip::getcode(const char* key) {
lastbit++;
if (lastbit == allocatedbit) {
allocatedbit += BASEBITREC;
dec = (struct bit*)realloc(dec, allocatedbit * sizeof(struct bit));
dec.resize(allocatedbit);
}
dec[lastbit].v[0] = 0;
dec[lastbit].v[1] = 0;
@ -173,10 +171,6 @@ int Hunzip::getcode(const char* key) {
}
Hunzip::~Hunzip() {
if (dec)
free(dec);
if (fin)
fclose(fin);
if (filename)
free(filename);
}
@ -185,16 +179,17 @@ int Hunzip::getbuf() {
int p = 0;
int o = 0;
do {
if (inc == 0)
inbits = fread(in, 1, BUFSIZE, fin) * 8;
if (inc == 0) {
fin.read(in, BUFSIZE);
inbits = fin.gcount() * 8;
}
for (; inc < inbits; inc++) {
int b = (in[inc / 8] & (1 << (7 - (inc % 8)))) ? 1 : 0;
int oldp = p;
p = dec[p].v[b];
if (p == 0) {
if (oldp == lastbit) {
fclose(fin);
fin = NULL;
fin.close();
// add last odd byte
if (dec[lastbit].c[0])
out[o++] = dec[lastbit].c[1];
@ -212,11 +207,11 @@ int Hunzip::getbuf() {
return fail(MSG_FORMAT, filename);
}
const char* Hunzip::getline() {
bool Hunzip::getline(std::string& dest) {
char linebuf[BUFSIZE];
int l = 0, eol = 0, left = 0, right = 0;
if (bufsiz == -1)
return NULL;
return false;
while (l < bufsiz && !eol) {
linebuf[l++] = out[outc];
switch (out[outc]) {
@ -251,7 +246,7 @@ const char* Hunzip::getline() {
}
if (++outc == bufsiz) {
outc = 0;
bufsiz = fin ? getbuf() : -1;
bufsiz = fin.is_open() ? getbuf() : -1;
}
}
if (right)
@ -259,5 +254,6 @@ const char* Hunzip::getline() {
else
linebuf[l] = '\0';
strcpy(line + left, linebuf);
return line;
dest.assign(line);
return true;
}

Просмотреть файл

@ -41,12 +41,14 @@
/* hunzip: file decompression for sorted dictionaries with optional encryption,
* algorithm: prefix-suffix encoding and 16-bit Huffman encoding */
#ifndef _HUNZIP_HXX_
#define _HUNZIP_HXX_
#ifndef HUNZIP_HXX_
#define HUNZIP_HXX_
#include "hunvisapi.h"
#include <stdio.h>
#include <fstream>
#include <vector>
#define BUFSIZE 65536
#define HZIP_EXTENSION ".hz"
@ -68,9 +70,9 @@ class LIBHUNSPELL_DLL_EXPORTED Hunzip {
protected:
char* filename;
FILE* fin;
std::ifstream fin;
int bufsiz, lastbit, inc, inbits, outc;
struct bit* dec; // code table
std::vector<bit> dec; // code table
char in[BUFSIZE]; // input buffer
char out[BUFSIZE + 1]; // Huffman-decoded buffer
char line[BUFSIZE + 50]; // decoded line
@ -81,7 +83,8 @@ class LIBHUNSPELL_DLL_EXPORTED Hunzip {
public:
Hunzip(const char* filename, const char* key = NULL);
~Hunzip();
const char* getline();
bool is_open() { return fin.is_open(); }
bool getline(std::string& dest);
};
#endif

Просмотреть файл

@ -38,12 +38,12 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef _LANGNUM_HXX_
#define _LANGNUM_HXX_
#ifndef LANGNUM_HXX_
#define LANGNUM_HXX_
/*
language numbers for language specific codes
see http://l10n.openoffice.org/languages.html
see https://wiki.openoffice.org/w/index.php?title=Languages&oldid=230199
*/
enum {

Просмотреть файл

@ -36,15 +36,13 @@
#include "phonet.hxx"
void init_phonet_hash(phonetable& parms) {
int i, k;
for (i = 0; i < HASHSIZE; i++) {
for (int i = 0; i < HASHSIZE; i++) {
parms.hash[i] = -1;
}
for (i = 0; parms.rules[i][0] != '\0'; i += 2) {
for (int i = 0; parms.rules[i][0] != '\0'; i += 2) {
/** set hash value **/
k = (unsigned char)parms.rules[i][0];
int k = (unsigned char)parms.rules[i][0];
if (parms.hash[k] < 0) {
parms.hash[k] = i;
@ -73,9 +71,8 @@ static int myisalpha(char ch) {
std::string phonet(const std::string& inword, phonetable& parms) {
int i, k = 0, p, z;
int k0, n0, p0 = -333, z0;
int k0, n0, p0 = -333;
char c;
const char* s;
typedef unsigned char uchar;
size_t len = inword.size();
@ -90,15 +87,15 @@ std::string phonet(const std::string& inword, phonetable& parms) {
i = z = 0;
while ((c = word[i]) != '\0') {
int n = parms.hash[(uchar)c];
z0 = 0;
int z0 = 0;
if (n >= 0) {
if (n >= 0 && !parms.rules[n].empty()) {
/** check all rules for the same letter **/
while (parms.rules[n][0] == c) {
/** check whole string **/
k = 1; /** number of found letters **/
p = 5; /** default priority **/
s = parms.rules[n];
const char*s = parms.rules[n].c_str();
s++; /** important for (see below) "*(s-1)" **/
while (*s != '\0' && word[i + k] == *s && !isdigit((unsigned char)*s) &&
@ -142,13 +139,13 @@ std::string phonet(const std::string& inword, phonetable& parms) {
n0 = parms.hash[(uchar)c0];
// if (parms.followup && k > 1 && n0 >= 0
if (k > 1 && n0 >= 0 && p0 != (int)'-' && word[i + k] != '\0') {
if (k > 1 && n0 >= 0 && p0 != (int)'-' && word[i + k] != '\0' && !parms.rules[n0].empty()) {
/** test follow-up rule for "word[i+k]" **/
while (parms.rules[n0][0] == c0) {
/** check whole string **/
k0 = k;
p0 = 5;
s = parms.rules[n0];
s = parms.rules[n0].c_str();
s++;
while (*s != '\0' && word[i + k0] == *s &&
!isdigit((unsigned char)*s) &&
@ -206,9 +203,9 @@ std::string phonet(const std::string& inword, phonetable& parms) {
} /** end of follow-up stuff **/
/** replace string **/
s = parms.rules[n + 1];
p0 = (parms.rules[n][0] != '\0' &&
strchr(parms.rules[n] + 1, '<') != NULL)
s = parms.rules[n + 1].c_str();
p0 = (!parms.rules[n].empty() &&
strchr(parms.rules[n].c_str() + 1, '<') != NULL)
? 1
: 0;
if (p0 == 1 && z == 0) {
@ -241,8 +238,8 @@ std::string phonet(const std::string& inword, phonetable& parms) {
}
/** new "actual letter" **/
c = *s;
if (parms.rules[n][0] != '\0' &&
strstr(parms.rules[n] + 1, "^^") != NULL) {
if (!parms.rules[n].empty() &&
strstr(parms.rules[n].c_str() + 1, "^^") != NULL) {
if (c != '\0') {
target.push_back(c);
}

Просмотреть файл

@ -27,8 +27,8 @@
Porting from Aspell to Hunspell using C-like structs
*/
#ifndef __PHONETHXX__
#define __PHONETHXX__
#ifndef PHONET_HXX_
#define PHONET_HXX_
#define HASHSIZE 256
#define MAXPHONETLEN 256
@ -38,9 +38,7 @@
struct phonetable {
char utf8;
cs_info* lang;
int num;
char** rules;
std::vector<std::string> rules;
int hash[HASHSIZE];
};

Просмотреть файл

@ -90,104 +90,122 @@ RepList::RepList(int n) {
RepList::~RepList() {
for (int i = 0; i < pos; i++) {
free(dat[i]->pattern);
free(dat[i]->pattern2);
free(dat[i]);
delete dat[i];
}
free(dat);
}
int RepList::get_pos() {
return pos;
}
replentry* RepList::item(int n) {
return dat[n];
}
int RepList::near(const char* word) {
int RepList::find(const char* word) {
int p1 = 0;
int p2 = pos;
while ((p2 - p1) > 1) {
int p2 = pos - 1;
while (p1 <= p2) {
int m = (p1 + p2) / 2;
int c = strcmp(word, dat[m]->pattern);
if (c <= 0) {
if (c < 0)
p2 = m;
else
p1 = p2 = m;
} else
p1 = m;
}
return p1;
}
int RepList::match(const char* word, int n) {
if (strncmp(word, dat[n]->pattern, strlen(dat[n]->pattern)) == 0)
return strlen(dat[n]->pattern);
return 0;
}
int RepList::add(char* pat1, char* pat2) {
if (pos >= size || pat1 == NULL || pat2 == NULL)
return 1;
replentry* r = (replentry*)malloc(sizeof(replentry));
if (r == NULL)
return 1;
r->pattern = mystrrep(pat1, "_", " ");
r->pattern2 = mystrrep(pat2, "_", " ");
r->start = false;
r->end = false;
dat[pos++] = r;
for (int i = pos - 1; i > 0; i--) {
r = dat[i];
if (strcmp(r->pattern, dat[i - 1]->pattern) < 0) {
dat[i] = dat[i - 1];
dat[i - 1] = r;
} else
break;
}
return 0;
}
int RepList::conv(const char* word, char* dest, size_t destsize) {
size_t stl = 0;
int change = 0;
for (size_t i = 0; i < strlen(word); i++) {
int n = near(word + i);
int l = match(word + i, n);
if (l) {
size_t replen = strlen(dat[n]->pattern2);
if (stl + replen >= destsize)
return -1;
strcpy(dest + stl, dat[n]->pattern2);
stl += replen;
i += l - 1;
change = 1;
} else {
if (stl + 1 >= destsize)
return -1;
dest[stl++] = word[i];
int c = strncmp(word, dat[m]->pattern.c_str(), dat[m]->pattern.size());
if (c < 0)
p2 = m - 1;
else if (c > 0)
p1 = m + 1;
else { // scan back for a longer match
for (p1 = m - 1; p1 >= 0; --p1)
if (!strncmp(word, dat[p1]->pattern.c_str(), dat[p1]->pattern.size()))
m = p1;
else if (dat[p1]->pattern.size() < dat[m]->pattern.size())
break;
return m;
}
}
dest[stl] = '\0';
return change;
return -1;
}
bool RepList::conv(const char* word, std::string& dest) {
std::string RepList::replace(const char* word, int ind, bool atstart) {
int type = atstart ? 1 : 0;
if (ind < 0)
return std::string();
if (strlen(word) == dat[ind]->pattern.size())
type = atstart ? 3 : 2;
while (type && dat[ind]->outstrings[type].empty())
type = (type == 2 && !atstart) ? 0 : type - 1;
return dat[ind]->outstrings[type];
}
int RepList::add(const std::string& in_pat1, const std::string& pat2) {
if (pos >= size || in_pat1.empty() || pat2.empty()) {
return 1;
}
// analyse word context
int type = 0;
std::string pat1(in_pat1);
if (pat1[0] == '_') {
pat1.erase(0, 1);
type = 1;
}
if (!pat1.empty() && pat1[pat1.size() - 1] == '_') {
type = type + 2;
pat1.erase(pat1.size() - 1);
}
mystrrep(pat1, "_", " ");
// find existing entry
int m = find(pat1.c_str());
if (m >= 0 && dat[m]->pattern == pat1) {
// since already used
dat[m]->outstrings[type] = pat2;
mystrrep(dat[m]->outstrings[type], "_", " ");
return 0;
}
// make a new entry if none exists
replentry* r = new replentry;
if (r == NULL)
return 1;
r->pattern = pat1;
r->outstrings[type] = pat2;
mystrrep(r->outstrings[type], "_", " ");
dat[pos++] = r;
// sort to the right place in the list
int i;
for (i = pos - 1; i > 0; i--) {
int c = strncmp(r->pattern.c_str(), dat[i-1]->pattern.c_str(), dat[i-1]->pattern.size());
if (c > 0)
break;
else if (c == 0) { // subpatterns match. Patterns can't be identical since would catch earlier
for (int j = i - 2; j > 0 && !strncmp(dat[i-1]->pattern.c_str(), dat[j]->pattern.c_str(), dat[i-1]->pattern.size()); --j)
if (dat[j]->pattern.size() > r->pattern.size() ||
(dat[j]->pattern.size() == r->pattern.size() && strncmp(dat[j]->pattern.c_str(), r->pattern.c_str(), r->pattern.size()) > 0)) {
i = j;
break;
}
break;
}
}
memmove(dat + i + 1, dat + i, (pos - i - 1) * sizeof(replentry *));
dat[i] = r;
return 0;
}
bool RepList::conv(const std::string& in_word, std::string& dest) {
dest.clear();
size_t wordlen = in_word.size();
const char* word = in_word.c_str();
bool change = false;
for (size_t i = 0; i < strlen(word); i++) {
int n = near(word + i);
int l = match(word + i, n);
if (l) {
dest.append(dat[n]->pattern2);
i += l - 1;
for (size_t i = 0; i < wordlen; ++i) {
int n = find(word + i);
std::string l = replace(word + i, n, i == 0);
if (!l.empty()) {
dest.append(l);
i += dat[n]->pattern.size() - 1;
change = true;
} else {
dest.push_back(word[i]);
}
}
return change;
}

Просмотреть файл

@ -72,17 +72,15 @@
*/
/* string replacement list class */
#ifndef _REPLIST_HXX_
#define _REPLIST_HXX_
#include "hunvisapi.h"
#ifndef REPLIST_HXX_
#define REPLIST_HXX_
#include "w_char.hxx"
#include <string>
#include <vector>
class LIBHUNSPELL_DLL_EXPORTED RepList {
class RepList {
private:
RepList(const RepList&);
RepList& operator=(const RepList&);
@ -93,15 +91,13 @@ class LIBHUNSPELL_DLL_EXPORTED RepList {
int pos;
public:
RepList(int n);
explicit RepList(int n);
~RepList();
int get_pos();
int add(char* pat1, char* pat2);
int add(const std::string& pat1, const std::string& pat2);
replentry* item(int n);
int near(const char* word);
int match(const char* word, int n);
int conv(const char* word, char* dest, size_t destsize);
bool conv(const char* word, std::string& dest);
int find(const char* word);
std::string replace(const char* word, int n, bool atstart);
bool conv(const std::string& word, std::string& dest);
};
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -71,8 +71,8 @@
* SUCH DAMAGE.
*/
#ifndef _SUGGESTMGR_HXX_
#define _SUGGESTMGR_HXX_
#ifndef SUGGESTMGR_HXX_
#define SUGGESTMGR_HXX_
#define MAX_ROOTS 100
#define MAX_WORDS 100
@ -91,8 +91,6 @@
#define NGRAM_LOWERING (1 << 2)
#define NGRAM_WEIGHTED (1 << 3)
#include "hunvisapi.h"
#include "atypes.hxx"
#include "affixmgr.hxx"
#include "hashmgr.hxx"
@ -101,22 +99,22 @@
enum { LCS_UP, LCS_LEFT, LCS_UPLEFT };
class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
class SuggestMgr {
private:
SuggestMgr(const SuggestMgr&);
SuggestMgr& operator=(const SuggestMgr&);
private:
char* ckey;
int ckeyl;
w_char* ckey_utf;
size_t ckeyl;
std::vector<w_char> ckey_utf;
char* ctry;
int ctryl;
w_char* ctry_utf;
size_t ctryl;
std::vector<w_char> ctry_utf;
AffixMgr* pAMgr;
int maxSug;
unsigned int maxSug;
struct cs_info* csconv;
int utf8;
int langnum;
@ -126,62 +124,53 @@ class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
int complexprefixes;
public:
SuggestMgr(const char* tryme, int maxn, AffixMgr* aptr);
SuggestMgr(const char* tryme, unsigned int maxn, AffixMgr* aptr);
~SuggestMgr();
int suggest(char*** slst, const char* word, int nsug, int* onlycmpdsug);
int ngsuggest(char** wlst, const char* word, int ns, HashMgr** pHMgr, int md);
int suggest_auto(char*** slst, const char* word, int nsug);
int suggest_stems(char*** slst, const char* word, int nsug);
int suggest_pos_stems(char*** slst, const char* word, int nsug);
void suggest(std::vector<std::string>& slst, const char* word, int* onlycmpdsug);
void ngsuggest(std::vector<std::string>& slst, const char* word, const std::vector<HashMgr*>& rHMgr);
char* suggest_morph(const char* word);
char* suggest_gen(char** pl, int pln, const char* pattern);
char* suggest_morph_for_spelling_error(const char* word);
std::string suggest_morph(const std::string& word);
std::string suggest_gen(const std::vector<std::string>& pl, const std::string& pattern);
private:
int testsug(char** wlst,
const char* candidate,
int wl,
int ns,
int cpdsuggest,
int* timer,
clock_t* timelimit);
int checkword(const char*, int, int, int*, clock_t*);
void testsug(std::vector<std::string>& wlst,
const std::string& candidate,
int cpdsuggest,
int* timer,
clock_t* timelimit);
int checkword(const std::string& word, int, int*, clock_t*);
int check_forbidden(const char*, int);
int capchars(char**, const char*, int, int);
int replchars(char**, const char*, int, int);
int doubletwochars(char**, const char*, int, int);
int forgotchar(char**, const char*, int, int);
int swapchar(char**, const char*, int, int);
int longswapchar(char**, const char*, int, int);
int movechar(char**, const char*, int, int);
int extrachar(char**, const char*, int, int);
int badcharkey(char**, const char*, int, int);
int badchar(char**, const char*, int, int);
int twowords(char**, const char*, int, int);
int fixstems(char**, const char*, int);
void capchars(std::vector<std::string>&, const char*, int);
int replchars(std::vector<std::string>&, const char*, int);
int doubletwochars(std::vector<std::string>&, const char*, int);
int forgotchar(std::vector<std::string>&, const char*, int);
int swapchar(std::vector<std::string>&, const char*, int);
int longswapchar(std::vector<std::string>&, const char*, int);
int movechar(std::vector<std::string>&, const char*, int);
int extrachar(std::vector<std::string>&, const char*, int);
int badcharkey(std::vector<std::string>&, const char*, int);
int badchar(std::vector<std::string>&, const char*, int);
int twowords(std::vector<std::string>&, const char*, int);
int capchars_utf(char**, const w_char*, int wl, int, int);
int doubletwochars_utf(char**, const w_char*, int wl, int, int);
int forgotchar_utf(char**, const w_char*, int wl, int, int);
int extrachar_utf(char**, const w_char*, int wl, int, int);
int badcharkey_utf(char**, const w_char*, int wl, int, int);
int badchar_utf(char**, const w_char*, int wl, int, int);
int swapchar_utf(char**, const w_char*, int wl, int, int);
int longswapchar_utf(char**, const w_char*, int, int, int);
int movechar_utf(char**, const w_char*, int, int, int);
void capchars_utf(std::vector<std::string>&, const w_char*, int wl, int);
int doubletwochars_utf(std::vector<std::string>&, const w_char*, int wl, int);
int forgotchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
int extrachar_utf(std::vector<std::string>&, const w_char*, int wl, int);
int badcharkey_utf(std::vector<std::string>&, const w_char*, int wl, int);
int badchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
int swapchar_utf(std::vector<std::string>&, const w_char*, int wl, int);
int longswapchar_utf(std::vector<std::string>&, const w_char*, int, int);
int movechar_utf(std::vector<std::string>&, const w_char*, int, int);
int mapchars(char**, const char*, int, int);
int mapchars(std::vector<std::string>&, const char*, int);
int map_related(const char*,
std::string&,
int,
char** wlst,
int,
int,
const mapentry*,
std::vector<std::string>& wlst,
int,
const std::vector<mapentry>&,
int*,
clock_t*);
int ngram(int n, const std::string& s1, const std::string& s2, int opt);
@ -192,7 +181,7 @@ class LIBHUNSPELL_DLL_EXPORTED SuggestMgr {
void lcs(const char* s, const char* s2, int* l1, int* l2, char** result);
int lcslen(const char* s, const char* s2);
int lcslen(const std::string& s, const std::string& s2);
char* suggest_hentry_gen(hentry* rv, const char* pattern);
std::string suggest_hentry_gen(hentry* rv, const char* pattern);
};
#endif

Просмотреть файл

@ -38,8 +38,10 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef __WCHARHXX__
#define __WCHARHXX__
#ifndef W_CHAR_HXX_
#define W_CHAR_HXX_
#include <string>
#ifndef GCC
struct w_char {
@ -66,10 +68,8 @@ struct __attribute__((packed)) w_char {
// two character arrays
struct replentry {
char* pattern;
char* pattern2;
bool start;
bool end;
std::string pattern;
std::string outstrings[4]; // med, ini, fin, isol
};
#endif

Просмотреть файл

@ -5,7 +5,7 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
include('/ipc/chromium/chromium-config.mozbuild')
SOURCES += [
UNIFIED_SOURCES += [
'mozEnglishWordUtils.cpp',
'mozInlineSpellChecker.cpp',
'mozInlineSpellWordUtil.cpp',

Просмотреть файл

@ -1608,6 +1608,11 @@ js::RegExpPrototypeOptimizableRaw(JSContext* cx, JSObject* proto, uint8_t* resul
if (!GetGetterPure(cx, proto, NameToId(cx->names().flags), &flagsGetter))
return false;
if (!flagsGetter) {
*result = false;
return true;
}
if (!IsSelfHostedFunctionWithName(flagsGetter, cx->names().RegExpFlagsGetter)) {
*result = false;
return true;

Просмотреть файл

@ -100,4 +100,30 @@
#define MODULE_STATE_INSTANTIATED 2
#define MODULE_STATE_EVALUATED 3
#define STRING_GENERICS_CHAR_AT 0
#define STRING_GENERICS_CHAR_CODE_AT 1
#define STRING_GENERICS_CONCAT 2
#define STRING_GENERICS_ENDS_WITH 3
#define STRING_GENERICS_INCLUDES 4
#define STRING_GENERICS_INDEX_OF 5
#define STRING_GENERICS_LAST_INDEX_OF 6
#define STRING_GENERICS_LOCALE_COMPARE 7
#define STRING_GENERICS_MATCH 8
#define STRING_GENERICS_NORMALIZE 9
#define STRING_GENERICS_REPLACE 10
#define STRING_GENERICS_SEARCH 11
#define STRING_GENERICS_SLICE 12
#define STRING_GENERICS_SPLIT 13
#define STRING_GENERICS_STARTS_WITH 14
#define STRING_GENERICS_SUBSTR 15
#define STRING_GENERICS_SUBSTRING 16
#define STRING_GENERICS_TO_LOWER_CASE 17
#define STRING_GENERICS_TO_LOCALE_LOWER_CASE 18
#define STRING_GENERICS_TO_LOCALE_UPPER_CASE 19
#define STRING_GENERICS_TO_UPPER_CASE 20
#define STRING_GENERICS_TRIM 21
#define STRING_GENERICS_TRIM_LEFT 22
#define STRING_GENERICS_TRIM_RIGHT 23
#define STRING_GENERICS_METHODS_LIMIT 24
#endif

Просмотреть файл

@ -58,6 +58,7 @@ function String_match(regexp) {
}
function String_generic_match(thisValue, regexp) {
WarnDeprecatedStringMethod(STRING_GENERICS_MATCH, 'match');
if (thisValue === undefined)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.match');
return callFunction(String_match, thisValue, regexp);
@ -192,6 +193,7 @@ function String_replace(searchValue, replaceValue) {
}
function String_generic_replace(thisValue, searchValue, replaceValue) {
WarnDeprecatedStringMethod(STRING_GENERICS_REPLACE, 'replace');
if (thisValue === undefined)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.replace');
return callFunction(String_replace, thisValue, searchValue, replaceValue);
@ -247,6 +249,7 @@ function String_search(regexp) {
}
function String_generic_search(thisValue, regexp) {
WarnDeprecatedStringMethod(STRING_GENERICS_SEARCH, 'search');
if (thisValue === undefined)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.search');
return callFunction(String_search, thisValue, regexp);
@ -328,6 +331,7 @@ function String_split(separator, limit) {
}
function String_generic_split(thisValue, separator, limit) {
WarnDeprecatedStringMethod(STRING_GENERICS_SPLIT, 'split');
if (thisValue === undefined)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.split');
return callFunction(String_split, thisValue, separator, limit);
@ -372,6 +376,7 @@ function String_substring(start, end) {
}
function String_static_substring(string, start, end) {
WarnDeprecatedStringMethod(STRING_GENERICS_SUBSTRING, 'substring');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.substring');
return callFunction(String_substring, string, start, end);
@ -411,6 +416,7 @@ function String_substr(start, length) {
}
function String_static_substr(string, start, length) {
WarnDeprecatedStringMethod(STRING_GENERICS_SUBSTR, 'substr');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.substr');
return callFunction(String_substr, string, start, length);
@ -448,6 +454,7 @@ function String_slice(start, end) {
}
function String_static_slice(string, start, end) {
WarnDeprecatedStringMethod(STRING_GENERICS_SLICE, 'slice');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.slice');
return callFunction(String_slice, string, start, end);
@ -655,6 +662,7 @@ function String_static_raw(callSite, ...substitutions) {
* Spec: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String#String_generic_methods
*/
function String_static_localeCompare(str1, str2) {
WarnDeprecatedStringMethod(STRING_GENERICS_LOCALE_COMPARE, 'localeCompare');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, "String.localeCompare");
var locales = arguments.length > 2 ? arguments[2] : undefined;
@ -767,30 +775,35 @@ function String_link(url) {
}
function String_static_toLowerCase(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOWER_CASE, 'toLowerCase');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLowerCase');
return callFunction(std_String_toLowerCase, string);
}
function String_static_toUpperCase(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TO_UPPER_CASE, 'toUpperCase');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toUpperCase');
return callFunction(std_String_toUpperCase, string);
}
function String_static_charAt(string, pos) {
WarnDeprecatedStringMethod(STRING_GENERICS_CHAR_AT, 'charAt');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charAt');
return callFunction(std_String_charAt, string, pos);
}
function String_static_charCodeAt(string, pos) {
WarnDeprecatedStringMethod(STRING_GENERICS_CHAR_CODE_AT, 'charCodeAt');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.charCodeAt');
return callFunction(std_String_charCodeAt, string, pos);
}
function String_static_includes(string, searchString) {
WarnDeprecatedStringMethod(STRING_GENERICS_INCLUDES, 'includes');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.includes');
var position = arguments.length > 2 ? arguments[2] : undefined;
@ -798,6 +811,7 @@ function String_static_includes(string, searchString) {
}
function String_static_indexOf(string, searchString) {
WarnDeprecatedStringMethod(STRING_GENERICS_INDEX_OF, 'indexOf');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.indexOf');
var position = arguments.length > 2 ? arguments[2] : undefined;
@ -805,6 +819,7 @@ function String_static_indexOf(string, searchString) {
}
function String_static_lastIndexOf(string, searchString) {
WarnDeprecatedStringMethod(STRING_GENERICS_LAST_INDEX_OF, 'lastIndexOf');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.lastIndexOf');
var position = arguments.length > 2 ? arguments[2] : undefined;
@ -812,6 +827,7 @@ function String_static_lastIndexOf(string, searchString) {
}
function String_static_startsWith(string, searchString) {
WarnDeprecatedStringMethod(STRING_GENERICS_STARTS_WITH, 'startsWith');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.startsWith');
var position = arguments.length > 2 ? arguments[2] : undefined;
@ -819,6 +835,7 @@ function String_static_startsWith(string, searchString) {
}
function String_static_endsWith(string, searchString) {
WarnDeprecatedStringMethod(STRING_GENERICS_ENDS_WITH, 'endsWith');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.endsWith');
var endPosition = arguments.length > 2 ? arguments[2] : undefined;
@ -826,30 +843,35 @@ function String_static_endsWith(string, searchString) {
}
function String_static_trim(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM, 'trim');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trim');
return callFunction(std_String_trim, string);
}
function String_static_trimLeft(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM_LEFT, 'trimLeft');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimLeft');
return callFunction(std_String_trimLeft, string);
}
function String_static_trimRight(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TRIM_RIGHT, 'trimRight');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.trimRight');
return callFunction(std_String_trimRight, string);
}
function String_static_toLocaleLowerCase(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOCALE_LOWER_CASE, 'toLocaleLowerCase');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleLowerCase');
return callFunction(std_String_toLocaleLowerCase, string);
}
function String_static_toLocaleUpperCase(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_TO_LOCALE_UPPER_CASE, 'toLocaleUpperCase');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.toLocaleUpperCase');
return callFunction(std_String_toLocaleUpperCase, string);
@ -857,6 +879,7 @@ function String_static_toLocaleUpperCase(string) {
#if EXPOSE_INTL_API
function String_static_normalize(string) {
WarnDeprecatedStringMethod(STRING_GENERICS_NORMALIZE, "normalize");
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.normalize');
var form = arguments.length > 1 ? arguments[1] : undefined;
@ -865,6 +888,7 @@ function String_static_normalize(string) {
#endif
function String_static_concat(string, arg1) {
WarnDeprecatedStringMethod(STRING_GENERICS_CONCAT, 'concat');
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'String.concat');
var args = callFunction(std_Array_slice, arguments, 1);

Просмотреть файл

@ -944,6 +944,17 @@ BaselineCacheIRCompiler::emitGuardIsSymbol()
return true;
}
bool
BaselineCacheIRCompiler::emitGuardIsInt32()
{
ValueOperand input = allocator.useValueRegister(masm, reader.valOperandId());
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
masm.branchTestInt32(Assembler::NotEqual, input, failure->label());
return true;
}
bool
BaselineCacheIRCompiler::emitGuardType()
{
@ -1561,13 +1572,101 @@ bool
BaselineCacheIRCompiler::emitLoadStringLengthResult()
{
Register str = allocator.useRegister(masm, reader.stringOperandId());
AutoScratchRegister scratch(allocator, masm);
masm.loadStringLength(str, R0.scratchReg());
masm.tagValue(JSVAL_TYPE_INT32, R0.scratchReg(), R0);
return true;
}
bool
BaselineCacheIRCompiler::emitLoadStringCharResult()
{
Register str = allocator.useRegister(masm, reader.stringOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
masm.branchIfRope(str, failure->label());
// Bounds check, load string char.
masm.branch32(Assembler::BelowOrEqual, Address(str, JSString::offsetOfLength()),
index, failure->label());
masm.loadStringChar(str, index, scratch);
// Load StaticString for this char.
masm.branch32(Assembler::AboveOrEqual, scratch, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
failure->label());
masm.movePtr(ImmPtr(&cx_->staticStrings().unitStaticTable), R0.scratchReg());
masm.loadPtr(BaseIndex(R0.scratchReg(), scratch, ScalePointer), R0.scratchReg());
masm.tagValue(JSVAL_TYPE_STRING, R0.scratchReg(), R0);
return true;
}
bool
BaselineCacheIRCompiler::emitLoadFrameArgumentResult()
{
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Bounds check.
masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs()), scratch);
masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
// Load the argument.
masm.loadValue(BaseValueIndex(BaselineFrameReg, index, BaselineFrame::offsetOfArg(0)), R0);
return true;
}
bool
BaselineCacheIRCompiler::emitLoadArgumentsObjectArgResult()
{
Register obj = allocator.useRegister(masm, reader.objOperandId());
Register index = allocator.useRegister(masm, reader.int32OperandId());
AutoScratchRegister scratch(allocator, masm);
FailurePath* failure;
if (!addFailurePath(&failure))
return false;
// Get initial length value.
masm.unboxInt32(Address(obj, ArgumentsObject::getInitialLengthSlotOffset()), scratch);
// Ensure no overridden length/element.
masm.branchTest32(Assembler::NonZero,
scratch,
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
failure->label());
// Bounds check.
masm.rshift32(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratch);
masm.branch32(Assembler::AboveOrEqual, index, scratch, failure->label());
// Load ArgumentsData.
masm.loadPrivate(Address(obj, ArgumentsObject::getDataSlotOffset()), scratch);
// Fail if we have a RareArgumentsData (elements were deleted).
masm.branchPtr(Assembler::NotEqual,
Address(scratch, offsetof(ArgumentsData, rareData)),
ImmWord(0),
failure->label());
// Guard the argument is not a FORWARD_TO_CALL_SLOT MagicValue. Note that
// the order here matters: we should only clobber R0 after emitting the last
// guard.
BaseValueIndex argValue(scratch, index, ArgumentsData::offsetOfArgs());
masm.branchTestMagic(Assembler::Equal, argValue, failure->label());
masm.loadValue(argValue, R0);
return true;
}
bool
BaselineCacheIRCompiler::emitTypeMonitorResult()
{

Просмотреть файл

@ -865,18 +865,6 @@ TypedArrayGetElemStubExists(ICGetElem_Fallback* stub, HandleObject obj)
return false;
}
static bool
ArgumentsGetElemStubExists(ICGetElem_Fallback* stub, ICGetElem_Arguments::Which which)
{
for (ICStubConstIterator iter = stub->beginChainConst(); !iter.atEnd(); iter++) {
if (!iter->isGetElem_Arguments())
continue;
if (iter->toGetElem_Arguments()->which() == which)
return true;
}
return false;
}
static bool
IsOptimizableElementPropertyName(JSContext* cx, HandleValue key, MutableHandleId idp)
{
@ -951,64 +939,10 @@ static bool
TryAttachGetElemStub(JSContext* cx, JSScript* script, jsbytecode* pc, ICGetElem_Fallback* stub,
HandleValue lhs, HandleValue rhs, HandleValue res, bool* attached)
{
// Check for String[i] => Char accesses.
if (lhs.isString() && rhs.isInt32() && res.isString() &&
!stub->hasStub(ICStub::GetElem_String))
{
// NoSuchMethod handling doesn't apply to string targets.
JitSpew(JitSpew_BaselineIC, " Generating GetElem(String[Int32]) stub");
ICGetElem_String::Compiler compiler(cx);
ICStub* stringStub = compiler.getStub(compiler.getStubSpace(script));
if (!stringStub)
return false;
stub->addNewStub(stringStub);
*attached = true;
return true;
}
if (lhs.isMagic(JS_OPTIMIZED_ARGUMENTS) && rhs.isInt32() &&
!ArgumentsGetElemStubExists(stub, ICGetElem_Arguments::Magic))
{
JitSpew(JitSpew_BaselineIC, " Generating GetElem(MagicArgs[Int32]) stub");
ICGetElem_Arguments::Compiler compiler(cx, stub->fallbackMonitorStub()->firstMonitorStub(),
ICGetElem_Arguments::Magic);
ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
if (!argsStub)
return false;
stub->addNewStub(argsStub);
*attached = true;
return true;
}
// Otherwise, GetElem is only optimized on objects.
if (!lhs.isObject())
return true;
RootedObject obj(cx, &lhs.toObject());
// Check for ArgumentsObj[int] accesses
if (obj->is<ArgumentsObject>() && rhs.isInt32() &&
!obj->as<ArgumentsObject>().hasOverriddenElement())
{
ICGetElem_Arguments::Which which = ICGetElem_Arguments::Mapped;
if (obj->is<UnmappedArgumentsObject>())
which = ICGetElem_Arguments::Unmapped;
if (!ArgumentsGetElemStubExists(stub, which)) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(ArgsObj[Int32]) stub");
ICGetElem_Arguments::Compiler compiler(
cx, stub->fallbackMonitorStub()->firstMonitorStub(), which);
ICStub* argsStub = compiler.getStub(compiler.getStubSpace(script));
if (!argsStub)
return false;
stub->addNewStub(argsStub);
*attached = true;
return true;
}
}
// Check for NativeObject[int] dense accesses.
if (IsNativeDenseElementAccess(obj, rhs)) {
JitSpew(JitSpew_BaselineIC, " Generating GetElem(Native[Int32] dense) stub");
@ -1192,56 +1126,6 @@ ICGetElem_Fallback::Compiler::generateStubCode(MacroAssembler& masm)
return tailCallVM(DoGetElemFallbackInfo, masm);
}
//
// GetElem_String
//
bool
ICGetElem_String::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
masm.branchTestString(Assembler::NotEqual, R0, &failure);
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
// Unbox string in R0.
Register str = masm.extractString(R0, ExtractTemp0);
// Check for non-linear strings.
masm.branchIfRope(str, &failure);
// Unbox key.
Register key = masm.extractInt32(R1, ExtractTemp1);
// Bounds check.
masm.branch32(Assembler::BelowOrEqual, Address(str, JSString::offsetOfLength()),
key, &failure);
// Get char code.
masm.loadStringChar(str, key, scratchReg);
// Check if char code >= UNIT_STATIC_LIMIT.
masm.branch32(Assembler::AboveOrEqual, scratchReg, Imm32(StaticStrings::UNIT_STATIC_LIMIT),
&failure);
// Load static string.
masm.movePtr(ImmPtr(&cx->staticStrings().unitStaticTable), str);
masm.loadPtr(BaseIndex(str, scratchReg, ScalePointer), str);
// Return.
masm.tagValue(JSVAL_TYPE_STRING, str, R0);
EmitReturnFromIC(masm);
// Failure case - jump to next stub
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// GetElem_Dense
//
@ -1422,131 +1306,6 @@ ICGetElem_TypedArray::Compiler::generateStubCode(MacroAssembler& masm)
return true;
}
//
// GetElem_Arguments
//
bool
ICGetElem_Arguments::Compiler::generateStubCode(MacroAssembler& masm)
{
MOZ_ASSERT(engine_ == Engine::Baseline);
Label failure;
if (which_ == ICGetElem_Arguments::Magic) {
// Ensure that this is a magic arguments value.
masm.branchTestMagicValue(Assembler::NotEqual, R0, JS_OPTIMIZED_ARGUMENTS, &failure);
// Ensure that frame has not loaded different arguments object since.
masm.branchTest32(Assembler::NonZero,
Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfFlags()),
Imm32(BaselineFrame::HAS_ARGS_OBJ),
&failure);
// Ensure that index is an integer.
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
Register idx = masm.extractInt32(R1, ExtractTemp1);
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratch = regs.takeAny();
// Load num actual arguments
Address actualArgs(BaselineFrameReg, BaselineFrame::offsetOfNumActualArgs());
masm.loadPtr(actualArgs, scratch);
// Ensure idx < argc
masm.branch32(Assembler::AboveOrEqual, idx, scratch, &failure);
// Load argval
masm.movePtr(BaselineFrameReg, scratch);
masm.addPtr(Imm32(BaselineFrame::offsetOfArg(0)), scratch);
BaseValueIndex element(scratch, idx);
masm.loadValue(element, R0);
// Enter type monitor IC to type-check result.
EmitEnterTypeMonitorIC(masm);
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
MOZ_ASSERT(which_ == ICGetElem_Arguments::Mapped ||
which_ == ICGetElem_Arguments::Unmapped);
const Class* clasp = (which_ == ICGetElem_Arguments::Mapped)
? &MappedArgumentsObject::class_
: &UnmappedArgumentsObject::class_;
AllocatableGeneralRegisterSet regs(availableGeneralRegs(2));
Register scratchReg = regs.takeAny();
// Guard on input being an arguments object.
masm.branchTestObject(Assembler::NotEqual, R0, &failure);
Register objReg = masm.extractObject(R0, ExtractTemp0);
masm.branchTestObjClass(Assembler::NotEqual, objReg, scratchReg, clasp, &failure);
// Guard on index being int32
masm.branchTestInt32(Assembler::NotEqual, R1, &failure);
Register idxReg = masm.extractInt32(R1, ExtractTemp1);
// Get initial ArgsObj length value.
masm.unboxInt32(Address(objReg, ArgumentsObject::getInitialLengthSlotOffset()), scratchReg);
// Test if length or any element have been overridden.
masm.branchTest32(Assembler::NonZero,
scratchReg,
Imm32(ArgumentsObject::LENGTH_OVERRIDDEN_BIT |
ArgumentsObject::ELEMENT_OVERRIDDEN_BIT),
&failure);
// Length has not been overridden, ensure that R1 is an integer and is <= length.
masm.rshiftPtr(Imm32(ArgumentsObject::PACKED_BITS_COUNT), scratchReg);
masm.branch32(Assembler::AboveOrEqual, idxReg, scratchReg, &failure);
// Length check succeeded, now check the correct bit. We clobber potential type regs
// now. Inputs will have to be reconstructed if we fail after this point, but that's
// unlikely.
Label failureReconstructInputs;
regs = availableGeneralRegs(0);
regs.takeUnchecked(objReg);
regs.takeUnchecked(idxReg);
regs.take(scratchReg);
Register argData = regs.takeAny();
// Load ArgumentsData
masm.loadPrivate(Address(objReg, ArgumentsObject::getDataSlotOffset()), argData);
// Fail if we have a RareArgumentsData (elements were deleted).
masm.branchPtr(Assembler::NotEqual,
Address(argData, offsetof(ArgumentsData, rareData)),
ImmWord(0),
&failureReconstructInputs);
// Load the value. Use scratchReg to form a ValueOperand to load into.
masm.addPtr(Imm32(ArgumentsData::offsetOfArgs()), argData);
regs.add(scratchReg);
ValueOperand tempVal = regs.takeAnyValue();
masm.loadValue(BaseValueIndex(argData, idxReg), tempVal);
// Makesure that this is not a FORWARD_TO_CALL_SLOT magic value.
masm.branchTestMagic(Assembler::Equal, tempVal, &failureReconstructInputs);
// Copy value from temp to R0.
masm.moveValue(tempVal, R0);
// Type-check result
EmitEnterTypeMonitorIC(masm);
// Failed, but inputs are deconstructed into object and int, and need to be
// reconstructed into values.
masm.bind(&failureReconstructInputs);
masm.tagValue(JSVAL_TYPE_OBJECT, objReg, R0);
masm.tagValue(JSVAL_TYPE_INT32, idxReg, R1);
masm.bind(&failure);
EmitStubGuardFailure(masm);
return true;
}
//
// SetElem_Fallback
//
@ -7420,13 +7179,6 @@ ICGetElem_TypedArray::ICGetElem_TypedArray(JitCode* stubCode, Shape* shape, Scal
MOZ_ASSERT(extra_ == type);
}
/* static */ ICGetElem_Arguments*
ICGetElem_Arguments::Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetElem_Arguments& other)
{
return New<ICGetElem_Arguments>(cx, space, other.jitCode(), firstMonitorStub, other.which());
}
ICSetElem_DenseOrUnboxedArray::ICSetElem_DenseOrUnboxedArray(JitCode* stubCode, Shape* shape, ObjectGroup* group)
: ICUpdatedStub(SetElem_DenseOrUnboxedArray, stubCode),
shape_(shape),

Просмотреть файл

@ -419,29 +419,6 @@ class ICGetElem_Fallback : public ICMonitoredFallbackStub
};
};
class ICGetElem_String : public ICStub
{
friend class ICStubSpace;
explicit ICGetElem_String(JitCode* stubCode)
: ICStub(ICStub::GetElem_String, stubCode) {}
public:
// Compiler for this stub kind.
class Compiler : public ICStubCompiler {
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
public:
explicit Compiler(JSContext* cx)
: ICStubCompiler(cx, ICStub::GetElem_String, Engine::Baseline) {}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICGetElem_String>(space, getStubCode());
}
};
};
class ICGetElem_Dense : public ICMonitoredStub
{
friend class ICStubSpace;
@ -583,53 +560,6 @@ class ICGetElem_TypedArray : public ICStub
};
};
class ICGetElem_Arguments : public ICMonitoredStub
{
friend class ICStubSpace;
public:
enum Which { Mapped, Unmapped, Magic };
private:
ICGetElem_Arguments(JitCode* stubCode, ICStub* firstMonitorStub, Which which)
: ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
{
extra_ = static_cast<uint16_t>(which);
}
public:
static ICGetElem_Arguments* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
ICGetElem_Arguments& other);
Which which() const {
return static_cast<Which>(extra_);
}
class Compiler : public ICStubCompiler {
ICStub* firstMonitorStub_;
Which which_;
protected:
MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
virtual int32_t getKey() const {
return static_cast<int32_t>(engine_) |
(static_cast<int32_t>(kind) << 1) |
(static_cast<int32_t>(which_) << 17);
}
public:
Compiler(JSContext* cx, ICStub* firstMonitorStub, Which which)
: ICStubCompiler(cx, ICStub::GetElem_Arguments, Engine::Baseline),
firstMonitorStub_(firstMonitorStub),
which_(which)
{}
ICStub* getStub(ICStubSpace* space) {
return newStub<ICGetElem_Arguments>(space, getStubCode(), firstMonitorStub_, which_);
}
};
};
// SetElem
// JSOP_SETELEM
// JSOP_INITELEM

Просмотреть файл

@ -49,11 +49,9 @@ namespace jit {
_(Call_IsSuspendedStarGenerator) \
\
_(GetElem_Fallback) \
_(GetElem_String) \
_(GetElem_Dense) \
_(GetElem_UnboxedArray) \
_(GetElem_TypedArray) \
_(GetElem_Arguments) \
\
_(SetElem_Fallback) \
_(SetElem_DenseOrUnboxedArray) \

Просмотреть файл

@ -1016,11 +1016,6 @@ BaselineInspector::expectedPropertyAccessInputType(jsbytecode* pc)
case ICStub::GetProp_Generic:
return MIRType::Value;
case ICStub::GetElem_Arguments:
// Either an object or magic arguments.
return MIRType::Value;
case ICStub::GetElem_String:
case ICStub::GetElem_Dense:
case ICStub::GetElem_TypedArray:
case ICStub::GetElem_UnboxedArray:

Просмотреть файл

@ -85,6 +85,13 @@ GetPropIRGenerator::tryAttachStub()
return true;
if (tryAttachProxy(obj, objId, id))
return true;
return false;
}
if (idVal_.isInt32()) {
ValOperandId indexId = getElemKeyValueId();
if (tryAttachArgumentsObjectArg(obj, objId, indexId))
return true;
return false;
}
return false;
}
@ -94,8 +101,18 @@ GetPropIRGenerator::tryAttachStub()
return true;
if (tryAttachStringLength(valId, id))
return true;
if (tryAttachMagicArguments(valId, id))
if (tryAttachMagicArgumentsName(valId, id))
return true;
return false;
}
if (idVal_.isInt32()) {
ValOperandId indexId = getElemKeyValueId();
if (tryAttachStringChar(valId, indexId))
return true;
if (tryAttachMagicArgument(valId, indexId))
return true;
return false;
}
return false;
@ -775,7 +792,31 @@ GetPropIRGenerator::tryAttachStringLength(ValOperandId valId, HandleId id)
}
bool
GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
GetPropIRGenerator::tryAttachStringChar(ValOperandId valId, ValOperandId indexId)
{
MOZ_ASSERT(idVal_.isInt32());
if (!val_.isString())
return false;
JSString* str = val_.toString();
int32_t index = idVal_.toInt32();
if (size_t(index) >= str->length() ||
!str->isLinear() ||
str->asLinear().latin1OrTwoByteChar(index) >= StaticStrings::UNIT_STATIC_LIMIT)
{
return false;
}
StringOperandId strId = writer.guardIsString(valId);
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
writer.loadStringCharResult(strId, int32IndexId);
writer.returnFromIC();
return true;
}
bool
GetPropIRGenerator::tryAttachMagicArgumentsName(ValOperandId valId, HandleId id)
{
if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
return false;
@ -799,6 +840,45 @@ GetPropIRGenerator::tryAttachMagicArguments(ValOperandId valId, HandleId id)
return true;
}
bool
GetPropIRGenerator::tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId)
{
MOZ_ASSERT(idVal_.isInt32());
if (!val_.isMagic(JS_OPTIMIZED_ARGUMENTS))
return false;
writer.guardMagicValue(valId, JS_OPTIMIZED_ARGUMENTS);
writer.guardFrameHasNoArgumentsObject();
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
writer.loadFrameArgumentResult(int32IndexId);
writer.typeMonitorResult();
return true;
}
bool
GetPropIRGenerator::tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId,
ValOperandId indexId)
{
MOZ_ASSERT(idVal_.isInt32());
if (!obj->is<ArgumentsObject>() || obj->as<ArgumentsObject>().hasOverriddenElement())
return false;
if (obj->is<MappedArgumentsObject>()) {
writer.guardClass(objId, GuardClassKind::MappedArguments);
} else {
MOZ_ASSERT(obj->is<UnmappedArgumentsObject>());
writer.guardClass(objId, GuardClassKind::UnmappedArguments);
}
Int32OperandId int32IndexId = writer.guardIsInt32(indexId);
writer.loadArgumentsObjectArgResult(objId, int32IndexId);
writer.typeMonitorResult();
return true;
}
void
GetPropIRGenerator::maybeEmitIdGuard(jsid id)
{

Просмотреть файл

@ -93,6 +93,13 @@ class SymbolOperandId : public OperandId
explicit SymbolOperandId(uint16_t id) : OperandId(id) {}
};
class Int32OperandId : public OperandId
{
public:
Int32OperandId() = default;
explicit Int32OperandId(uint16_t id) : OperandId(id) {}
};
class TypedOperandId : public OperandId
{
JSValueType type_;
@ -107,6 +114,9 @@ class TypedOperandId : public OperandId
MOZ_IMPLICIT TypedOperandId(SymbolOperandId id)
: OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL)
{}
MOZ_IMPLICIT TypedOperandId(Int32OperandId id)
: OperandId(id.id()), type_(JSVAL_TYPE_INT32)
{}
JSValueType type() const { return type_; }
};
@ -121,6 +131,7 @@ enum class CacheKind : uint8_t
_(GuardIsObject) \
_(GuardIsString) \
_(GuardIsSymbol) \
_(GuardIsInt32) \
_(GuardType) \
_(GuardShape) \
_(GuardGroup) \
@ -150,10 +161,13 @@ enum class CacheKind : uint8_t
_(LoadTypedObjectResult) \
_(LoadInt32ArrayLengthResult) \
_(LoadUnboxedArrayLengthResult) \
_(LoadArgumentsObjectArgResult) \
_(LoadArgumentsObjectLengthResult) \
_(LoadStringCharResult) \
_(LoadStringLengthResult) \
_(LoadFrameCalleeResult) \
_(LoadFrameNumActualArgsResult) \
_(LoadFrameArgumentResult) \
_(CallScriptedGetterResult) \
_(CallNativeGetterResult) \
_(CallProxyGetResult) \
@ -368,6 +382,10 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
return SymbolOperandId(val.id());
}
Int32OperandId guardIsInt32(ValOperandId val) {
writeOpWithOperandId(CacheOp::GuardIsInt32, val);
return Int32OperandId(val.id());
}
void guardType(ValOperandId val, JSValueType type) {
writeOpWithOperandId(CacheOp::GuardType, val);
static_assert(sizeof(type) == sizeof(uint8_t), "JSValueType should fit in a byte");
@ -425,6 +443,9 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
void loadFrameNumActualArgsResult() {
writeOp(CacheOp::LoadFrameNumActualArgsResult);
}
void loadFrameArgumentResult(Int32OperandId index) {
writeOpWithOperandId(CacheOp::LoadFrameArgumentResult, index);
}
void guardNoUnboxedExpando(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::GuardNoUnboxedExpando, obj);
}
@ -501,12 +522,20 @@ class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
void loadUnboxedArrayLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
}
void loadArgumentsObjectArgResult(ObjOperandId obj, Int32OperandId index) {
writeOpWithOperandId(CacheOp::LoadArgumentsObjectArgResult, obj);
writeOperandId(index);
}
void loadArgumentsObjectLengthResult(ObjOperandId obj) {
writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
}
void loadStringLengthResult(StringOperandId str) {
writeOpWithOperandId(CacheOp::LoadStringLengthResult, str);
}
void loadStringCharResult(StringOperandId str, Int32OperandId index) {
writeOpWithOperandId(CacheOp::LoadStringCharResult, str);
writeOperandId(index);
}
void callScriptedGetterResult(ObjOperandId obj, JSFunction* getter) {
writeOpWithOperandId(CacheOp::CallScriptedGetterResult, obj);
addStubField(uintptr_t(getter), StubField::Type::JSObject);
@ -561,6 +590,7 @@ class MOZ_RAII CacheIRReader
ObjOperandId objOperandId() { return ObjOperandId(buffer_.readByte()); }
StringOperandId stringOperandId() { return StringOperandId(buffer_.readByte()); }
SymbolOperandId symbolOperandId() { return SymbolOperandId(buffer_.readByte()); }
Int32OperandId int32OperandId() { return Int32OperandId(buffer_.readByte()); }
uint32_t stubOffset() { return buffer_.readByte() * sizeof(uintptr_t); }
GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
@ -623,8 +653,12 @@ class MOZ_RAII GetPropIRGenerator
bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
bool tryAttachPrimitive(ValOperandId valId, HandleId id);
bool tryAttachStringChar(ValOperandId valId, ValOperandId indexId);
bool tryAttachStringLength(ValOperandId valId, HandleId id);
bool tryAttachMagicArguments(ValOperandId valId, HandleId id);
bool tryAttachMagicArgumentsName(ValOperandId valId, HandleId id);
bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
bool tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId, ValOperandId indexId);
ValOperandId getElemKeyValueId() const {
MOZ_ASSERT(cacheKind_ == CacheKind::GetElem);

Просмотреть файл

@ -1505,6 +1505,11 @@ IonBuilder::visitBlock(const CFGBlock* cfgblock, MBasicBlock* mblock)
if (mblock->pc() && script()->hasScriptCounts())
mblock->setHitCount(script()->getHitCount(mblock->pc()));
// Optimization to move a predecessor that only has this block as successor
// just before this block.
if (mblock->numPredecessors() == 1 && mblock->getPredecessor(0)->numSuccessors() == 1)
graph().moveBlockToEnd(mblock->getPredecessor(0));
if (!setCurrentAndSpecializePhis(mblock))
return false;
graph().addBlock(mblock);
@ -2846,6 +2851,9 @@ IonBuilder::visitTest(CFGTest* test)
return false;
filterBlock->end(MGoto::New(alloc(), ifFalse));
if (filterBlock->pc() && script()->hasScriptCounts())
filterBlock->setHitCount(script()->getHitCount(filterBlock->pc()));
blockWorklist[test->falseBranch()->id()] = ifFalse;
current = nullptr;
@ -3079,6 +3087,9 @@ IonBuilder::visitTableSwitch(CFGTableSwitch* cfgIns)
}
graph().addBlock(caseBlock);
if (caseBlock->pc() && script()->hasScriptCounts())
caseBlock->setHitCount(script()->getHitCount(caseBlock->pc()));
MBasicBlock* merge = newBlock(caseBlock, cfgblock->startPc());
if (!merge)
return false;

Просмотреть файл

@ -133,6 +133,7 @@ MSG_DEF(JSMSG_INVALID_NORMALIZE_FORM, 0, JSEXN_RANGEERR, "form must be one of '
MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 0, JSEXN_RANGEERR, "repeat count must be non-negative")
MSG_DEF(JSMSG_NOT_A_CODEPOINT, 1, JSEXN_RANGEERR, "{0} is not a valid code point")
MSG_DEF(JSMSG_RESULTING_STRING_TOO_LARGE, 0, JSEXN_RANGEERR, "repeat count must be less than infinity and not overflow maximum string size")
MSG_DEF(JSMSG_DEPRECATED_STRING_METHOD, 2, JSEXN_WARN, "String.{0} is deprecated; use String.prototype.{1} instead")
// Number
MSG_DEF(JSMSG_BAD_RADIX, 0, JSEXN_RANGEERR, "radix must be an integer at least 2 and no greater than 36")

Просмотреть файл

@ -55,6 +55,7 @@ JSCompartment::JSCompartment(Zone* zone, const JS::CompartmentOptions& options =
marked(true),
warnedAboutExprClosure(false),
warnedAboutForEach(false),
warnedAboutStringGenericsMethods(0),
#ifdef DEBUG
firedOnNewGlobalObject(false),
#endif

Просмотреть файл

@ -361,6 +361,7 @@ struct JSCompartment
bool marked;
bool warnedAboutExprClosure;
bool warnedAboutForEach;
uint32_t warnedAboutStringGenericsMethods;
#ifdef DEBUG
bool firedOnNewGlobalObject;
@ -882,6 +883,7 @@ struct JSCompartment
// NO LONGER USING 8
// NO LONGER USING 9
DeprecatedBlockScopeFunRedecl = 10,
DeprecatedStringGenerics = 11,
DeprecatedLanguageExtensionCount
};

Просмотреть файл

@ -0,0 +1,11 @@
var BUGNUMBER = 1322319;
var summary = "RegExp.prototype.split should throw if RegRxp.prototype.flags is deleted."
print(BUGNUMBER + ": " + summary);
delete RegExp.prototype.flags;
assertThrowsInstanceOf(() => "aaaaa".split(/a/), SyntaxError);
if (typeof reportCompare === "function")
reportCompare(true, true);

Просмотреть файл

@ -0,0 +1,63 @@
// |reftest| skip-if(!xulRuntime.shell)
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// Warn once for each String generics method.
var methods = {
charAt: ["", 0],
charCodeAt: ["", 0],
concat: ["", ""],
endsWith: ["", ""],
includes: ["", ""],
indexOf: ["", ""],
lastIndexOf: ["", ""],
localeCompare: ["", ""],
match: ["", ""],
normalize: [""],
replace: ["", ""],
search: ["", ""],
slice: ["", 0],
split: ["", ""],
startsWith: ["", ""],
substr: ["", 0],
substring: ["", 0],
toLowerCase: [""],
toLocaleLowerCase: [""],
toLocaleUpperCase: [""],
toUpperCase: [""],
trim: [""],
trimLeft: [""],
trimRight: [""]
};
for (var name in methods) {
var args = methods[name];
// String.normalize not available on every platform.
if (name === "normalize" && !(name in String.prototype))
continue;
enableLastWarning();
String[name].apply(null, args);
var warning = getLastWarning();
assertEq(warning !== null, true, "warning should be emitted for " + name);
assertEq(warning.name, "Warning");
assertEq(warning.message.indexOf(name) !== -1, true,
"warning should mention " + name);
clearLastWarning();
String[name].apply(null, args);
warning = getLastWarning();
assertEq(warning, null, "warning shouldn't be emitted for 2nd call to " + name);
disableLastWarning();
}
if (typeof reportCompare === 'function')
reportCompare(0, 0);

Просмотреть файл

@ -1904,6 +1904,46 @@ intrinsic_AddContentTelemetry(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
intrinsic_WarnDeprecatedStringMethod(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
MOZ_ASSERT(args.length() == 2);
MOZ_ASSERT(args[0].isInt32());
MOZ_ASSERT(args[1].isString());
uint32_t id = uint32_t(args[0].toInt32());
MOZ_ASSERT(id < STRING_GENERICS_METHODS_LIMIT);
NonBuiltinScriptFrameIter iter(cx);
if (!iter.done()) {
const char* filename = iter.filename();
iter.compartment()->addTelemetry(filename, JSCompartment::DeprecatedStringGenerics);
}
uint32_t mask = (1 << id);
if (!(cx->compartment()->warnedAboutStringGenericsMethods & mask)) {
JSFlatString* name = args[1].toString()->ensureFlat(cx);
if (!name)
return false;
AutoStableStringChars stableChars(cx);
if (!stableChars.initTwoByte(cx, name))
return false;
const char16_t* nameChars = stableChars.twoByteRange().begin().get();
if (!JS_ReportErrorFlagsAndNumberUC(cx, JSREPORT_WARNING, GetErrorMessage, nullptr,
JSMSG_DEPRECATED_STRING_METHOD, nameChars, nameChars))
{
return false;
}
cx->compartment()->warnedAboutStringGenericsMethods |= mask;
}
args.rval().setUndefined();
return true;
}
static bool
intrinsic_ConstructFunction(JSContext* cx, unsigned argc, Value* vp)
{
@ -2513,6 +2553,7 @@ static const JSFunctionSpec intrinsic_functions[] = {
JS_INLINABLE_FN("StringSplitString", intrinsic_StringSplitString, 2, 0,
IntrinsicStringSplitString),
JS_FN("StringSplitStringLimit", intrinsic_StringSplitStringLimit, 3, 0),
JS_FN("WarnDeprecatedStringMethod", intrinsic_WarnDeprecatedStringMethod, 2, 0),
// See builtin/RegExp.h for descriptions of the regexp_* functions.
JS_FN("regexp_exec_no_statics", regexp_exec_no_statics, 2,0),

Просмотреть файл

@ -278,13 +278,14 @@ TraceLoggerThread::disable(bool force, const char* error)
}
const char*
TraceLoggerThread::eventText(uint32_t id)
TraceLoggerThread::maybeEventText(uint32_t id)
{
if (id < TraceLogger_Last)
return TLTextIdString(static_cast<TraceLoggerTextId>(id));
TextIdHashMap::Ptr p = textIdPayloads.lookup(id);
MOZ_ASSERT(p);
if (!p)
return nullptr;
return p->value()->string();
}
@ -570,7 +571,10 @@ TraceLoggerThread::stopEvent(uint32_t id)
MOZ_ASSERT(prev >= TraceLogger_Last);
} else if (id >= TraceLogger_Last) {
MOZ_ASSERT(prev >= TraceLogger_Last);
MOZ_ASSERT_IF(prev != id, strcmp(eventText(id), eventText(prev)) == 0);
if (prev != id) {
// Ignore if the text has been flushed already.
MOZ_ASSERT_IF(maybeEventText(prev), strcmp(eventText(id), eventText(prev)) == 0);
}
} else {
MOZ_ASSERT(id == prev);
}

Просмотреть файл

@ -260,7 +260,14 @@ class TraceLoggerThread
return true;
}
const char* eventText(uint32_t id);
private:
const char* maybeEventText(uint32_t id);
public:
const char* eventText(uint32_t id) {
const char* text = maybeEventText(id);
MOZ_ASSERT(text);
return text;
};
bool textIdIsScriptEvent(uint32_t id);
// The createTextId functions map a unique input to a logger ID.

Просмотреть файл

@ -3173,6 +3173,8 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
builder.SetDescendIntoSubdocuments(false);
}
builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
builder.EnterPresShell(aFrame);
aFrame->BuildDisplayListForStackingContext(&builder, aRect, &list);
builder.LeavePresShell(aFrame, nullptr);
@ -3188,7 +3190,6 @@ nsLayoutUtils::GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,
#endif
nsDisplayItem::HitTestState hitTestState;
builder.SetHitTestShouldStopAtFirstOpaque(aFlags & ONLY_VISIBLE);
list.HitTest(&builder, aRect, &hitTestState, &aOutFrames);
list.DeleteAll();
return NS_OK;

Просмотреть файл

@ -825,7 +825,7 @@ public:
* frames under the area of a rectangle that receives a mouse event,
* or nullptr if there is no such frame.
* @param aRect the rect, relative to the frame origin
* @param aOutFrames an array to add all the frames found
* @param aOutFrames an array to append all the frames found
* @param aFlags some combination of FrameForPointFlags
*/
static nsresult GetFramesForArea(nsIFrame* aFrame, const nsRect& aRect,

Просмотреть файл

@ -119,7 +119,7 @@ nsHTMLButtonControlFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
nsDisplayListCollection set;
// Do not allow the child subtree to receive events.
if (!isForEventDelivery) {
if (!isForEventDelivery || aBuilder->HitTestShouldStopAtFirstOpaque()) {
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (ShouldClipPaintingToBorderBox()) {

Просмотреть файл

@ -629,7 +629,7 @@ load text-overflow-form-elements.html
load text-overflow-iframe.html
asserts-if(Android,2-4) asserts-if(!Android,4) load 1225005.html # bug 682647 and bug 448083
load 1233191.html
asserts(3) load 1271765.html # bug 1319318
load 1271765.html
asserts(2) load 1272983-1.html # bug 586628
asserts(2) load 1272983-2.html # bug 586628
load 1275059.html

Просмотреть файл

@ -377,7 +377,9 @@ nsVideoFrame::Reflow(nsPresContext* aPresContext,
borderPadding.left, borderPadding.top, 0, aStatus);
if (child->GetContent() == mVideoControls && isBSizeShrinkWrapping) {
contentBoxBSize = kidDesiredSize.BSize(myWM);
// Resolve our own BSize based on the controls' size in the same axis.
contentBoxBSize = myWM.IsOrthogonalTo(wm) ?
kidDesiredSize.ISize(wm) : kidDesiredSize.BSize(wm);
}
FinishReflowChild(child, aPresContext,

Просмотреть файл

@ -48,7 +48,8 @@
#include "nsCSSProps.h"
#include "nsCSSValue.h"
#include "nsColor.h"
#include "nsStyleSet.h"
#include "mozilla/StyleSetHandle.h"
#include "mozilla/StyleSetHandleInlines.h"
#include "nsStyleUtil.h"
#include "nsQueryObject.h"
@ -77,7 +78,7 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
{
NS_ENSURE_ARG_POINTER(aDocument);
nsTArray<RefPtr<CSSStyleSheet>> sheets;
nsTArray<RefPtr<StyleSheet>> sheets;
nsCOMPtr<nsIDocument> document = do_QueryInterface(aDocument);
MOZ_ASSERT(document);
@ -85,15 +86,8 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
// Get the agent, then user and finally xbl sheets in the style set.
nsIPresShell* presShell = document->GetShell();
if (presShell && presShell->StyleSet()->IsServo()) {
// XXXheycam ServoStyleSets don't have the ability to expose their
// sheets in a script-accessible way yet.
NS_ERROR("stylo: ServoStyleSets cannot expose their sheets to script yet");
return NS_ERROR_FAILURE;
}
if (presShell) {
nsStyleSet* styleSet = presShell->StyleSet()->AsGecko();
StyleSetHandle styleSet = presShell->StyleSet();
SheetType sheetType = SheetType::Agent;
for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
@ -102,24 +96,26 @@ inDOMUtils::GetAllStyleSheets(nsIDOMDocument *aDocument, uint32_t *aLength,
for (int32_t i = 0; i < styleSet->SheetCount(sheetType); i++) {
sheets.AppendElement(styleSet->StyleSheetAt(sheetType, i));
}
AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
styleSet->AppendAllXBLStyleSheets(xblSheetArray);
if (styleSet->IsGecko()) {
AutoTArray<CSSStyleSheet*, 32> xblSheetArray;
styleSet->AsGecko()->AppendAllXBLStyleSheets(xblSheetArray);
// The XBL stylesheet array will quite often be full of duplicates. Cope:
nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
for (CSSStyleSheet* sheet : xblSheetArray) {
if (!sheetSet.Contains(sheet)) {
sheetSet.PutEntry(sheet);
sheets.AppendElement(sheet);
// The XBL stylesheet array will quite often be full of duplicates. Cope:
nsTHashtable<nsPtrHashKey<CSSStyleSheet>> sheetSet;
for (CSSStyleSheet* sheet : xblSheetArray) {
if (!sheetSet.Contains(sheet)) {
sheetSet.PutEntry(sheet);
sheets.AppendElement(sheet);
}
}
} else {
NS_WARNING("stylo: XBL style sheets not supported yet");
}
}
// Get the document sheets.
for (int32_t i = 0; i < document->GetNumberOfStyleSheets(); i++) {
// XXXheycam ServoStyleSets don't have the ability to expose their
// sheets in a script-accessible way yet.
sheets.AppendElement(document->GetStyleSheetAt(i)->AsGecko());
sheets.AppendElement(document->GetStyleSheetAt(i));
}
nsISupports** ret = static_cast<nsISupports**>(moz_xmalloc(sheets.Length() *

Просмотреть файл

@ -2965,6 +2965,7 @@ var gCSSProperties = {
"ruby-base-container",
"ruby-text",
"ruby-text-container",
"contents",
"none"
],
invalid_values: []
@ -6725,8 +6726,6 @@ if (IsCSSPropertyPrefEnabled("layout.css.grid.enabled")) {
};
}
gCSSProperties["display"].other_values.push("contents");
if (IsCSSPropertyPrefEnabled("layout.css.contain.enabled")) {
gCSSProperties["contain"] = {
domProp: "contain",

Просмотреть файл

@ -14,27 +14,14 @@ using namespace std;
#include "mozilla/SyncRunnable.h"
#include "mozilla/UniquePtr.h"
#include <MediaConduitInterface.h>
#include "GmpVideoCodec.h"
#include "nsIEventTarget.h"
#include "FakeMediaStreamsImpl.h"
#include "FakeLogging.h"
#include "nsThreadUtils.h"
#include "runnable_utils.h"
#include "signaling/src/common/EncodingConstraints.h"
#include "FakeIPC.h"
#include "FakeIPC.cpp"
#include "prmem.h"
#define GTEST_HAS_RTTI 0
#include "gtest/gtest.h"
#include "gtest_utils.h"
nsCOMPtr<nsIThread> gMainThread;
nsCOMPtr<nsIThread> gGtestThread;
bool gTestsComplete = false;
#include "mtransport_test_utils.h"
MtransportTestUtils *test_utils;
//Video Frame Color
const int COLOR = 0x80; //Gray
@ -128,7 +115,7 @@ int numFrames;
* A Dummy AudioConduit Tester
* The test reads PCM samples of a standard test file and
* passws to audio-conduit for encoding, RTPfication and
* decoding ebery 10 milliseconds.
* decoding every 10 milliseconds.
* This decoded samples are read-off the conduit for writing
* into output audio file in PCM format.
*/
@ -136,7 +123,7 @@ class AudioSendAndReceive
{
public:
static const unsigned int PLAYOUT_SAMPLE_FREQUENCY; //default is 16000
static const unsigned int PLAYOUT_SAMPLE_LENGTH; //default is 160000
static const unsigned int PLAYOUT_SAMPLE_LENGTH; //default is 160
AudioSendAndReceive()
{
@ -173,7 +160,7 @@ private:
};
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_FREQUENCY = 16000;
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH = 160000;
const unsigned int AudioSendAndReceive::PLAYOUT_SAMPLE_LENGTH = 160;
int AudioSendAndReceive::WriteWaveHeader(int rate, int channels, FILE* outFile)
{
@ -262,12 +249,7 @@ void AudioSendAndReceive::GenerateMusic(short* buf, int len)
a1=b1=a2=b2=0;
c1=c2=d1=d2=0;
j=0;
/*60ms silence */
for(i=0;i<2880;i++)
{
buf[i*2]=buf[(i*2)+1]=0;
}
for(i=2880;i<len-1;i+=2)
for(i=0;i<len-1;i+=2)
{
int32_t r;
int32_t v1,v2;
@ -294,7 +276,7 @@ void AudioSendAndReceive::GenerateAndReadSamples()
auto audioOutput = mozilla::MakeUnique<int16_t []>(PLAYOUT_SAMPLE_LENGTH);
short* inbuf;
int sampleLengthDecoded = 0;
unsigned int SAMPLES = (PLAYOUT_SAMPLE_FREQUENCY * 10); //10 seconds
unsigned int SAMPLES = (PLAYOUT_SAMPLE_FREQUENCY / 100); //10 milliseconds
int CHANNELS = 1; //mono audio
int sampleLengthInBytes = sizeof(int16_t) * PLAYOUT_SAMPLE_LENGTH;
//generated audio buffer
@ -337,7 +319,6 @@ void AudioSendAndReceive::GenerateAndReadSamples()
}
numSamplesReadFromInput += PLAYOUT_SAMPLE_LENGTH;
inbuf += PLAYOUT_SAMPLE_LENGTH;
mSession->SendAudioFrame(audioInput.get(),
PLAYOUT_SAMPLE_LENGTH,
@ -366,7 +347,7 @@ void AudioSendAndReceive::GenerateAndReadSamples()
/**
* Dummy Video Target for the conduit
* This class acts as renderer attached to the video conuit
* This class acts as renderer attached to the video conduit
* As of today we just verify if the frames rendered are exactly
* the same as frame inserted at the first place
*/
@ -509,8 +490,9 @@ private:
bool mAudio, mVideo;
};
using namespace mozilla;
namespace {
namespace test {
class TransportConduitTest : public ::testing::Test
{
@ -525,13 +507,6 @@ class TransportConduitTest : public ::testing::Test
~TransportConduitTest()
{
mozilla::SyncRunnable::DispatchToThread(gMainThread,
mozilla::WrapRunnable(
this,
&TransportConduitTest::SelfDestruct));
}
void SelfDestruct() {
mAudioSession = nullptr;
mAudioSession2 = nullptr;
mAudioTransport = nullptr;
@ -547,19 +522,13 @@ class TransportConduitTest : public ::testing::Test
{
//get pointer to AudioSessionConduit
int err=0;
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&mAudioSession,
&mozilla::AudioSessionConduit::Create));
if( !mAudioSession ) {
mAudioSession = mozilla::AudioSessionConduit::Create();
if( !mAudioSession )
ASSERT_NE(mAudioSession, (void*)nullptr);
}
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&mAudioSession2,
&mozilla::AudioSessionConduit::Create));
if( !mAudioSession2 ) {
mAudioSession2 = mozilla::AudioSessionConduit::Create();
if( !mAudioSession2 )
ASSERT_NE(mAudioSession2, (void*)nullptr);
}
WebrtcMediaTransport* xport = new WebrtcMediaTransport();
ASSERT_NE(xport, (void*)nullptr);
@ -600,9 +569,7 @@ class TransportConduitTest : public ::testing::Test
cerr << " ******************************************************** " << endl;
cerr << " Generating Audio Samples " << endl;
cerr << " ******************************************************** " << endl;
PR_Sleep(PR_SecondsToInterval(2));
audioTester.GenerateAndReadSamples();
PR_Sleep(PR_SecondsToInterval(2));
cerr << " ******************************************************** " << endl;
cerr << " Input Audio File " << iAudiofilename << endl;
cerr << " Output Audio File " << oAudiofilename << endl;
@ -610,28 +577,18 @@ class TransportConduitTest : public ::testing::Test
}
//2. Dump audio samples to dummy external transport
void TestDummyVideoAndTransport(bool send_vp8 = true, const char *source_file = nullptr)
void TestDummyVideoAndTransport(const char *source_file = nullptr)
{
int err = 0;
//get pointer to VideoSessionConduit
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&mVideoSession,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession ) {
mVideoSession = VideoSessionConduit::Create();
if( !mVideoSession )
ASSERT_NE(mVideoSession, (void*)nullptr);
}
// This session is for other one
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&mVideoSession2,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession2 ) {
// This session is for other one
mVideoSession2 = VideoSessionConduit::Create();
if( !mVideoSession2 )
ASSERT_NE(mVideoSession2,(void*)nullptr);
}
if (!send_vp8) {
SetGmpCodecs();
}
mVideoRenderer = new DummyVideoTarget();
ASSERT_NE(mVideoRenderer, (void*)nullptr);
@ -659,15 +616,13 @@ class TransportConduitTest : public ::testing::Test
rcvCodecList.push_back(&cinst1);
rcvCodecList.push_back(&cinst2);
err = mVideoSession->ConfigureSendMediaCodec(
send_vp8 ? &cinst1 : &cinst2);
err = mVideoSession->ConfigureSendMediaCodec(&cinst1);
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
err = mVideoSession->StartTransmitting();
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
err = mVideoSession2->ConfigureSendMediaCodec(
send_vp8 ? &cinst1 : &cinst2);
err = mVideoSession2->ConfigureSendMediaCodec(&cinst1);
err = mVideoSession2->StartTransmitting();
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
@ -679,10 +634,8 @@ class TransportConduitTest : public ::testing::Test
cerr << " *************************************************" << endl;
cerr << " Starting the Video Sample Generation " << endl;
cerr << " *************************************************" << endl;
PR_Sleep(PR_SecondsToInterval(2));
videoTester.Init(mVideoSession);
videoTester.GenerateAndReadSamples();
PR_Sleep(PR_SecondsToInterval(2));
cerr << " **************************************************" << endl;
cerr << " Done With The Testing " << endl;
@ -697,19 +650,10 @@ class TransportConduitTest : public ::testing::Test
cerr << " Done With The Testing " << endl;
cerr << " **************************************************" << endl;
ASSERT_EQ(0, vidStatsGlobal.numFramesRenderedWrongly);
if (send_vp8) {
ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
vidStatsGlobal.numFramesRenderedSuccessfully);
}
else {
// Allow some fudge because there seems to be some buffering.
// TODO(ekr@rtfm.com): Fix this.
ASSERT_GE(vidStatsGlobal.numRawFramesInserted,
vidStatsGlobal.numFramesRenderedSuccessfully);
ASSERT_LE(vidStatsGlobal.numRawFramesInserted,
vidStatsGlobal.numFramesRenderedSuccessfully + 2);
}
ASSERT_EQ(vidStatsGlobal.numRawFramesInserted,
vidStatsGlobal.numFramesRenderedSuccessfully);
}
void TestVideoConduitCodecAPI()
@ -717,12 +661,9 @@ class TransportConduitTest : public ::testing::Test
int err = 0;
RefPtr<mozilla::VideoSessionConduit> videoSession;
//get pointer to VideoSessionConduit
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&videoSession,
&mozilla::VideoSessionConduit::Create));
if( !videoSession ) {
videoSession = VideoSessionConduit::Create();
if( !videoSession )
ASSERT_NE(videoSession, (void*)nullptr);
}
//Test Configure Recv Codec APIS
cerr << " *************************************************" << endl;
@ -742,12 +683,11 @@ class TransportConduitTest : public ::testing::Test
rcvCodecList.push_back(&cinst1);
rcvCodecList.push_back(&cinst2);
err = videoSession->ConfigureRecvMediaCodecs(rcvCodecList);
EXPECT_NE(err,mozilla::kMediaConduitNoError);
EXPECT_EQ(err, mozilla::kMediaConduitNoError);
rcvCodecList.pop_back();
rcvCodecList.pop_back();
PR_Sleep(PR_SecondsToInterval(2));
cerr << " *************************************************" << endl;
cerr << " 2. Codec With Invalid Payload Names " << endl;
cerr << " *************************************************" << endl;
@ -766,7 +706,6 @@ class TransportConduitTest : public ::testing::Test
rcvCodecList.pop_back();
PR_Sleep(PR_SecondsToInterval(2));
cerr << " *************************************************" << endl;
cerr << " 3. Null Codec Parameter " << endl;
cerr << " *************************************************" << endl;
@ -791,7 +730,7 @@ class TransportConduitTest : public ::testing::Test
err = videoSession->StartTransmitting();
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
err = videoSession->ConfigureSendMediaCodec(&cinst1);
EXPECT_EQ(mozilla::kMediaConduitCodecInUse, err);
EXPECT_EQ(mozilla::kMediaConduitNoError, err);
err = videoSession->StartTransmitting();
ASSERT_EQ(mozilla::kMediaConduitNoError, err);
@ -810,11 +749,6 @@ class TransportConduitTest : public ::testing::Test
err = videoSession->ConfigureSendMediaCodec(nullptr);
EXPECT_TRUE(err != mozilla::kMediaConduitNoError);
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnable(
videoSession.forget().take(),
&mozilla::VideoSessionConduit::Release));
}
void DumpMaxFs(int orig_width, int orig_height, int max_fs,
@ -833,12 +767,9 @@ class TransportConduitTest : public ::testing::Test
int err = 0;
// Get pointer to VideoSessionConduit.
mozilla::SyncRunnable::DispatchToThread(gMainThread,
WrapRunnableNMRet(&mVideoSession,
&mozilla::VideoSessionConduit::Create));
if( !mVideoSession ) {
mVideoSession = VideoSessionConduit::Create();
if( !mVideoSession )
ASSERT_NE(mVideoSession, (void*)nullptr);
}
mozilla::EncodingConstraints constraints;
constraints.maxFs = max_fs;
@ -902,7 +833,7 @@ class TransportConduitTest : public ::testing::Test
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
ASSERT_EQ(width, 768);
ASSERT_EQ(height, 26);
ASSERT_EQ(height, 25);
// Small max-fs.
cerr << "Test small max-fs (case 1)" << endl;
@ -921,7 +852,7 @@ class TransportConduitTest : public ::testing::Test
max_fs = 1;
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
ASSERT_EQ(width, 2);
ASSERT_EQ(width, 1);
ASSERT_EQ(height, 16);
// Small max-fs.
@ -932,7 +863,7 @@ class TransportConduitTest : public ::testing::Test
GetVideoResolutionWithMaxFs(orig_width, orig_height, max_fs, &width, &height);
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
ASSERT_EQ(width, 48);
ASSERT_EQ(height, 8);
ASSERT_EQ(height, 7);
// Small max-fs.
cerr << "Test small max-fs (case 4)" << endl;
@ -969,23 +900,10 @@ class TransportConduitTest : public ::testing::Test
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
ADD_FAILURE();
}
if ((width & 1) || (height & 1)) {
DumpMaxFs(orig_width, orig_height, max_fs, width, height);
ADD_FAILURE();
}
}
cerr << endl;
}
void SetGmpCodecs() {
mExternalEncoder = mozilla::GmpVideoCodec::CreateEncoder();
mExternalDecoder = mozilla::GmpVideoCodec::CreateDecoder();
mozilla::EncodingConstraints constraints;
mozilla::VideoCodecConfig config(124, "H264", constraints);
mVideoSession->SetExternalSendCodec(&config, mExternalEncoder);
mVideoSession2->SetExternalRecvCodec(&config, mExternalDecoder);
}
private:
//Audio Conduit Test Objects
RefPtr<mozilla::AudioSessionConduit> mAudioSession;
@ -1000,9 +918,6 @@ class TransportConduitTest : public ::testing::Test
RefPtr<mozilla::TransportInterface> mVideoTransport;
VideoSendAndReceive videoTester;
mozilla::VideoEncoder* mExternalEncoder;
mozilla::VideoDecoder* mExternalDecoder;
std::string fileToPlay;
std::string fileToRecord;
std::string iAudiofilename;
@ -1011,19 +926,17 @@ class TransportConduitTest : public ::testing::Test
// Test 1: Test Dummy External Xport
TEST_F(TransportConduitTest, TestDummyAudioWithTransport) {
// See Bug 1319121
TEST_F(TransportConduitTest, DISABLED_TestDummyAudioWithTransport) {
TestDummyAudioAndTransport();
}
// Test 2: Test Dummy External Xport
TEST_F(TransportConduitTest, TestDummyVideoWithTransport) {
// See Bug 1319121
TEST_F(TransportConduitTest, DISABLED_TestDummyVideoWithTransport) {
TestDummyVideoAndTransport();
}
TEST_F(TransportConduitTest, TestVideoConduitExternalCodec) {
TestDummyVideoAndTransport(false);
}
TEST_F(TransportConduitTest, TestVideoConduitCodecAPI) {
TestVideoConduitCodecAPI();
}
@ -1033,65 +946,3 @@ TEST_F(TransportConduitTest, TestVideoConduitMaxFs) {
}
} // end namespace
static int test_result;
bool test_finished = false;
// This exists to send as an event to trigger shutdown.
static void tests_complete() {
gTestsComplete = true;
}
// The GTest thread runs this instead of the main thread so it can
// do things like ASSERT_TRUE_WAIT which you could not do on the main thread.
static int gtest_main(int argc, char **argv) {
MOZ_ASSERT(!NS_IsMainThread());
::testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
// Set the global shutdown flag and tickle the main thread
// The main thread did not go through Init() so calling Shutdown()
// on it will not work.
gMainThread->Dispatch(mozilla::WrapRunnableNM(tests_complete), NS_DISPATCH_SYNC);
return result;
}
int main(int argc, char **argv)
{
// This test can cause intermittent oranges on the builders
CHECK_ENVIRONMENT_FLAG("MOZ_WEBRTC_MEDIACONDUIT_TESTS")
test_utils = new MtransportTestUtils();
// Set the main thread global which is this thread.
nsIThread *thread;
NS_GetMainThread(&thread);
gMainThread = thread;
// Now create the GTest thread and run all of the tests on it
// When it is complete it will set gTestsComplete
NS_NewNamedThread("gtest_thread", &thread);
gGtestThread = thread;
int result;
gGtestThread->Dispatch(
mozilla::WrapRunnableNMRet(&result, gtest_main, argc, argv), NS_DISPATCH_NORMAL);
// Here we handle the event queue for dispatches to the main thread
// When the GTest thread is complete it will send one more dispatch
// with gTestsComplete == true.
while (!gTestsComplete && NS_ProcessNextEvent());
gGtestThread->Shutdown();
delete test_utils;
return test_result;
}

Просмотреть файл

@ -13,12 +13,15 @@ if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk' and
'/media/mtransport',
'/media/webrtc/',
'/media/webrtc/signaling/src/common/time_profiling',
'/media/webrtc/signaling/src/media-conduit',
'/media/webrtc/signaling/src/peerconnection',
'/media/webrtc/trunk/',
]
SOURCES += [
'jsep_session_unittest.cpp',
'jsep_track_unittest.cpp',
'mediaconduit_unittests.cpp',
'sdp_unittests.cpp',
]

Просмотреть файл

@ -7,7 +7,6 @@
# TODO: bug 1172551 - get these tests working on iOS
if CONFIG['OS_TARGET'] != 'WINNT' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'gonk' and CONFIG['MOZ_WIDGET_TOOLKIT'] != 'uikit':
GeckoCppUnitTests([
'mediaconduit_unittests',
'mediapipeline_unittest',
'signaling_unittests',
])

Просмотреть файл

@ -103,12 +103,9 @@ import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.FloatUtils;
import org.mozilla.gecko.util.GamepadUtils;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.GeckoEventListener;
import org.mozilla.gecko.util.HardwareUtils;
import org.mozilla.gecko.util.IntentUtils;
import org.mozilla.gecko.util.MenuUtils;
import org.mozilla.gecko.util.NativeEventListener;
import org.mozilla.gecko.util.NativeJSObject;
import org.mozilla.gecko.util.PrefUtils;
import org.mozilla.gecko.util.StringUtils;
import org.mozilla.gecko.util.ThreadUtils;
@ -202,8 +199,7 @@ public class BrowserApp extends GeckoApp
OnUrlOpenInBackgroundListener,
AnchoredPopup.OnVisibilityChangeListener,
ActionModeCompat.Presenter,
LayoutInflater.Factory,
BundleEventListener {
LayoutInflater.Factory {
private static final String LOGTAG = "GeckoBrowserApp";
private static final int TABS_ANIMATION_DURATION = 450;
@ -726,32 +722,36 @@ public class BrowserApp extends GeckoApp
mDoorhangerOverlay = findViewById(R.id.doorhanger_overlay);
EventDispatcher.getInstance().registerGeckoThreadListener((GeckoEventListener)this,
"Gecko:DelayedStartup",
EventDispatcher.getInstance().registerGeckoThreadListener(this,
"Search:Keyword",
"Favicon:CacheLoad",
null);
EventDispatcher.getInstance().registerUiThreadListener(this,
"Menu:Open",
"Menu:Update",
"Menu:Add",
"Menu:Remove",
"LightweightTheme:Update",
"Search:Keyword",
"Tab:Added",
"Video:Play");
EventDispatcher.getInstance().registerGeckoThreadListener((NativeEventListener)this,
"Video:Play",
"CharEncoding:Data",
"CharEncoding:State",
"Download:AndroidDownloadManager",
"Settings:Show",
"Updater:Launch",
null);
EventDispatcher.getInstance().registerBackgroundThreadListener(this,
"Experiments:GetActive",
"Experiments:SetOverride",
"Experiments:ClearOverride",
"Favicon:CacheLoad",
"Feedback:MaybeLater",
"Menu:Add",
"Menu:Remove",
"Sanitize:ClearHistory",
"Sanitize:ClearSyncedTabs",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch",
"Website:Metadata");
"Download:AndroidDownloadManager",
"Website:Metadata",
null);
getAppEventDispatcher().registerUiThreadListener(this, "Prompt:ShowTop");
@ -1430,32 +1430,36 @@ public class BrowserApp extends GeckoApp
mSearchEngineManager.unregisterListeners();
EventDispatcher.getInstance().unregisterGeckoThreadListener((GeckoEventListener) this,
"Gecko:DelayedStartup",
EventDispatcher.getInstance().unregisterGeckoThreadListener(this,
"Search:Keyword",
"Favicon:CacheLoad",
null);
EventDispatcher.getInstance().unregisterUiThreadListener(this,
"Menu:Open",
"Menu:Update",
"Menu:Add",
"Menu:Remove",
"LightweightTheme:Update",
"Search:Keyword",
"Tab:Added",
"Video:Play");
EventDispatcher.getInstance().unregisterGeckoThreadListener((NativeEventListener) this,
"Video:Play",
"CharEncoding:Data",
"CharEncoding:State",
"Download:AndroidDownloadManager",
"Settings:Show",
"Updater:Launch",
null);
EventDispatcher.getInstance().unregisterBackgroundThreadListener(this,
"Experiments:GetActive",
"Experiments:SetOverride",
"Experiments:ClearOverride",
"Favicon:CacheLoad",
"Feedback:MaybeLater",
"Menu:Add",
"Menu:Remove",
"Sanitize:ClearHistory",
"Sanitize:ClearSyncedTabs",
"Settings:Show",
"Telemetry:Gather",
"Updater:Launch",
"Website:Metadata");
"Download:AndroidDownloadManager",
"Website:Metadata",
null);
getAppEventDispatcher().unregisterUiThreadListener(this, "Prompt:ShowTop");
@ -1548,25 +1552,6 @@ public class BrowserApp extends GeckoApp
alphaAnimator.start();
}
private void handleClearHistory(final boolean clearSearchHistory) {
final BrowserDB db = BrowserDB.from(getProfile());
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
db.clearHistory(getContentResolver(), clearSearchHistory);
}
});
}
private void handleClearSyncedTabs() {
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
}
});
}
private void setToolbarMargin(int margin) {
((RelativeLayout.LayoutParams) mGeckoLayout.getLayoutParams()).topMargin = margin;
mGeckoLayout.requestLayout();
@ -1663,29 +1648,21 @@ public class BrowserApp extends GeckoApp
@Override
void toggleChrome(final boolean aShow) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (aShow) {
mBrowserChrome.setVisibility(View.VISIBLE);
} else {
mBrowserChrome.setVisibility(View.GONE);
}
}
});
if (aShow) {
mBrowserChrome.setVisibility(View.VISIBLE);
} else {
mBrowserChrome.setVisibility(View.GONE);
}
super.toggleChrome(aShow);
}
@Override
void focusChrome() {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mBrowserChrome.setVisibility(View.VISIBLE);
mActionBarFlipper.requestFocusFromTouch();
}
});
mBrowserChrome.setVisibility(View.VISIBLE);
mActionBarFlipper.requestFocusFromTouch();
super.focusChrome();
}
@Override
@ -1707,6 +1684,124 @@ public class BrowserApp extends GeckoApp
public void handleMessage(final String event, final GeckoBundle message,
final EventCallback callback) {
switch (event) {
case "Gecko:Ready":
EventDispatcher.getInstance().registerUiThreadListener(this, "Gecko:DelayedStartup");
// Handle this message in GeckoApp, but also enable the Settings
// menuitem, which is specific to BrowserApp.
super.handleMessage(event, message, callback);
final Menu menu = mMenu;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (menu != null) {
menu.findItem(R.id.settings).setEnabled(true);
menu.findItem(R.id.help).setEnabled(true);
}
}
});
// Display notification for Mozilla data reporting, if data should be collected.
if (AppConstants.MOZ_DATA_REPORTING &&
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
}
break;
case "Gecko:DelayedStartup":
EventDispatcher.getInstance().unregisterUiThreadListener(this, "Gecko:DelayedStartup");
// Force tabs panel inflation once the initial pageload is finished.
ensureTabsPanelExists();
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
mZoomedView = (ZoomedView) stub.inflate();
}
if (AppConstants.MOZ_MEDIA_PLAYER) {
// Check if the fragment is already added. This should never be true
// here, but this is a nice safety check. If casting is disabled,
// these classes aren't built. We use reflection to initialize them.
final Class<?> mediaManagerClass = getMediaPlayerManager();
if (mediaManagerClass != null) {
try {
final String tag = "";
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
Log.i(LOGTAG, "Found tag " + tag);
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
if (frag == null) {
final Method getInstance = mediaManagerClass.getMethod(
"getInstance", (Class[]) null);
final Fragment mpm = (Fragment) getInstance.invoke(null);
getSupportFragmentManager().beginTransaction()
.disallowAddToBackStack().add(mpm, tag).commit();
}
} catch (Exception ex) {
Log.e(LOGTAG, "Error initializing media manager", ex);
}
}
}
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED &&
Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
// Start (this acts as ping if started already) the stumbler lib; if
// the stumbler has queued data it will upload it. Stumbler operates
// on its own thread, and startup impact is further minimized by
// delaying work (such as upload) a few seconds. Avoid any potential
// startup CPU/thread contention by delaying the pref broadcast.
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
}
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
// TODO: Better scheduling of sync action (Bug 1257492)
DownloadContentService.startSync(this);
DownloadContentService.startVerification(this);
}
FeedService.setup(this);
break;
case "Menu:Open":
if (mBrowserToolbar.isEditing()) {
mBrowserToolbar.cancelEdit();
}
openOptionsMenu();
break;
case "Menu:Update":
updateAddonMenuItem(message.getInt("id"), message.getBundle("options"));
break;
case "Menu:Add":
final MenuItemInfo info = new MenuItemInfo();
info.label = message.getString("name");
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
info.checked = message.getBoolean("checked", false);
info.enabled = message.getBoolean("enabled", true);
info.visible = message.getBoolean("visible", true);
info.checkable = message.getBoolean("checkable", false);
final int parent = message.getInt("parent", 0);
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
addAddonMenuItem(info);
break;
case "Menu:Remove":
removeAddonMenuItem(message.getInt("id") + ADDON_MENU_OFFSET);
break;
case "LightweightTheme:Update":
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
break;
case "Search:Keyword":
storeSearchQuery(message.getString("query"));
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
TelemetryContract.Method.ACTIONBAR);
break;
case "Prompt:ShowTop":
// Bring this activity to front so the prompt is visible..
Intent bringToFrontIntent = new Intent();
@ -1715,21 +1810,32 @@ public class BrowserApp extends GeckoApp
bringToFrontIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(bringToFrontIntent);
break;
}
}
@Override
public void handleMessage(final String event, final NativeJSObject message,
final EventCallback callback) {
switch (event) {
case "Tab:Added":
if (message.getBoolean("cancelEditMode")) {
// Set the target tab to null so it does not get selected (on editing
// mode exit) in lieu of the tab that we're going to open and select.
mTargetTabForEditingMode = null;
mBrowserToolbar.cancelEdit();
}
break;
case "Video:Play":
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
mVideoPlayer.start(Uri.parse(message.getString("uri")));
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW,
TelemetryContract.Method.CONTENT, "playhls");
}
break;
case "CharEncoding:Data":
final NativeJSObject[] charsets = message.getObjectArray("charsets");
final GeckoBundle[] charsets = message.getBundleArray("charsets");
final int selected = message.getInt("selected");
final String[] titleArray = new String[charsets.length];
final String[] codeArray = new String[charsets.length];
for (int i = 0; i < charsets.length; i++) {
final NativeJSObject charset = charsets[i];
final GeckoBundle charset = charsets[i];
titleArray[i] = charset.getString("title");
codeArray[i] = charset.getString("code");
}
@ -1750,26 +1856,15 @@ public class BrowserApp extends GeckoApp
dialog.dismiss();
}
});
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
dialogBuilder.show();
}
});
dialogBuilder.show();
break;
case "CharEncoding:State":
final boolean visible = message.getString("visible").equals("true");
final boolean visible = "true".equals(message.getString("visible"));
GeckoPreferences.setCharEncodingState(visible);
final Menu menu = mMenu;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (menu != null) {
menu.findItem(R.id.char_encoding).setVisible(visible);
}
}
});
if (mMenu != null) {
mMenu.findItem(R.id.char_encoding).setVisible(visible);
}
break;
case "Experiments:GetActive":
@ -1779,7 +1874,8 @@ public class BrowserApp extends GeckoApp
break;
case "Experiments:SetOverride":
Experiments.setOverride(getContext(), message.getString("name"), message.getBoolean("isEnabled"));
Experiments.setOverride(getContext(), message.getString("name"),
message.getBoolean("isEnabled"));
break;
case "Experiments:ClearOverride":
@ -1792,52 +1888,25 @@ public class BrowserApp extends GeckoApp
break;
case "Feedback:MaybeLater":
resetFeedbackLaunchCount();
break;
case "Menu:Add":
final MenuItemInfo info = new MenuItemInfo();
info.label = message.getString("name");
info.id = message.getInt("id") + ADDON_MENU_OFFSET;
info.checked = message.optBoolean("checked", false);
info.enabled = message.optBoolean("enabled", true);
info.visible = message.optBoolean("visible", true);
info.checkable = message.optBoolean("checkable", false);
final int parent = message.optInt("parent", 0);
info.parent = parent <= 0 ? parent : parent + ADDON_MENU_OFFSET;
final MenuItemInfo menuItemInfo = info;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
addAddonMenuItem(menuItemInfo);
}
});
break;
case "Menu:Remove":
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
removeAddonMenuItem(id);
}
});
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
break;
case "Sanitize:ClearHistory":
handleClearHistory(message.optBoolean("clearSearchHistory", false));
callback.sendSuccess(true);
BrowserDB.from(getProfile()).clearHistory(
getContentResolver(), message.getBoolean("clearSearchHistory", false));
callback.sendSuccess(null);
break;
case "Sanitize:ClearSyncedTabs":
handleClearSyncedTabs();
callback.sendSuccess(true);
FennecTabsRepository.deleteNonLocalClientsAndTabs(getContext());
callback.sendSuccess(null);
break;
case "Settings:Show":
final String resource =
message.optString(GeckoPreferences.INTENT_EXTRA_RESOURCES, null);
final Intent settingsIntent = new Intent(this, GeckoPreferences.class);
final String resource = message.getString(GeckoPreferences.INTENT_EXTRA_RESOURCES);
GeckoPreferences.setResourceToOpen(settingsIntent, resource);
startActivityForResult(settingsIntent, ACTIVITY_REQUEST_PREFERENCES);
@ -1851,30 +1920,58 @@ public class BrowserApp extends GeckoApp
case "Telemetry:Gather":
final BrowserDB db = BrowserDB.from(getProfile());
final ContentResolver cr = getContentResolver();
Telemetry.addToHistogram("PLACES_PAGES_COUNT", db.getCount(cr, "history"));
Telemetry.addToHistogram("FENNEC_BOOKMARKS_COUNT", db.getCount(cr, "bookmarks"));
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT", (isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE", (TextUtils.isEmpty(getHomepage()) ? 0 : 1));
Telemetry.addToHistogram("BROWSER_IS_USER_DEFAULT",
(isDefaultBrowser(Intent.ACTION_VIEW) ? 1 : 0));
Telemetry.addToHistogram("FENNEC_CUSTOM_HOMEPAGE",
(TextUtils.isEmpty(getHomepage()) ? 0 : 1));
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
final boolean hasCustomHomepanels =
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) || prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY) ||
prefs.contains(HomeConfigPrefsBackend.PREFS_CONFIG_KEY_OLD);
Telemetry.addToHistogram("FENNEC_HOMEPANELS_CUSTOM", hasCustomHomepanels ? 1 : 0);
Telemetry.addToHistogram("FENNEC_READER_VIEW_CACHE_SIZE",
SavedReaderViewHelper.getSavedReaderViewHelper(getContext()).getDiskSpacedUsedKB());
SavedReaderViewHelper.getSavedReaderViewHelper(getContext())
.getDiskSpacedUsedKB());
if (Versions.feature16Plus) {
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT", (isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
Telemetry.addToHistogram("BROWSER_IS_ASSIST_DEFAULT",
(isDefaultBrowser(Intent.ACTION_ASSIST) ? 1 : 0));
}
break;
case "Updater:Launch":
handleUpdaterLaunch();
/**
* Launch UI that lets the user update Firefox.
*
* This depends on the current channel: Release and Beta both direct to
* the Google Play Store. If updating is enabled, Aurora, Nightly, and
* custom builds open about:, which provides an update interface.
*
* If updating is not enabled, this simply logs an error.
*/
if (AppConstants.RELEASE_OR_BETA) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
startActivity(intent);
break;
}
if (AppConstants.MOZ_UPDATER) {
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
break;
}
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
break;
case "Download:AndroidDownloadManager":
// Downloading via Android's download manager
final String uri = message.getString("uri");
final String filename = message.getString("filename");
final String mimeType = message.getString("mimeType");
@ -1883,54 +1980,49 @@ public class BrowserApp extends GeckoApp
request.setMimeType(mimeType);
try {
request.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, filename);
request.setDestinationInExternalFilesDir(
this, Environment.DIRECTORY_DOWNLOADS, filename);
} catch (IllegalStateException e) {
Log.e(LOGTAG, "Cannot create download directory");
return;
break;
}
request.allowScanningByMediaScanner();
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.setNotificationVisibility(
DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
request.addRequestHeader("User-Agent", HardwareUtils.isTablet() ?
AppConstants.USER_AGENT_FENNEC_TABLET :
AppConstants.USER_AGENT_FENNEC_MOBILE);
try {
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager manager = (DownloadManager)
getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);
Log.d(LOGTAG, "Enqueued download (Download Manager)");
} catch (RuntimeException e) {
Log.e(LOGTAG, "Download failed: " + e);
}
break;
case "Website:Metadata":
final NativeJSObject metadata = message.getObject("metadata");
final String location = message.getString("location");
final boolean hasImage = message.getBoolean("hasImage");
final String metadata = message.getString("metadata");
final boolean hasImage = !TextUtils.isEmpty(metadata.optString("image_url", null));
final String metadataJSON = metadata.toString();
ThreadUtils.postToBackgroundThread(new Runnable() {
@Override
public void run() {
final ContentProviderClient contentProviderClient = getContentResolver()
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
if (contentProviderClient == null) {
Log.w(LOGTAG, "Failed to obtain content provider client for: " + BrowserContract.PageMetadata.CONTENT_URI);
return;
}
try {
GlobalPageMetadata.getInstance().add(
BrowserDB.from(getProfile()),
contentProviderClient,
location, hasImage, metadataJSON);
} finally {
contentProviderClient.release();
}
}
});
final ContentProviderClient contentProviderClient = getContentResolver()
.acquireContentProviderClient(BrowserContract.PageMetadata.CONTENT_URI);
if (contentProviderClient == null) {
Log.w(LOGTAG, "Failed to obtain content provider client for: " +
BrowserContract.PageMetadata.CONTENT_URI);
return;
}
try {
GlobalPageMetadata.getInstance().add(
BrowserDB.from(getProfile()),
contentProviderClient,
location, hasImage, metadata);
} finally {
contentProviderClient.release();
}
break;
@ -1994,164 +2086,6 @@ public class BrowserApp extends GeckoApp
return (TextUtils.equals(packageName, getPackageName()));
}
@Override
public void handleMessage(String event, JSONObject message) {
try {
switch (event) {
case "Menu:Open":
if (mBrowserToolbar.isEditing()) {
mBrowserToolbar.cancelEdit();
}
openOptionsMenu();
break;
case "Menu:Update":
final int id = message.getInt("id") + ADDON_MENU_OFFSET;
final JSONObject options = message.getJSONObject("options");
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
updateAddonMenuItem(id, options);
}
});
break;
case "Gecko:DelayedStartup":
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
// Force tabs panel inflation once the initial
// pageload is finished.
ensureTabsPanelExists();
if (AppConstants.NIGHTLY_BUILD && mZoomedView == null) {
ViewStub stub = (ViewStub) findViewById(R.id.zoomed_view_stub);
mZoomedView = (ZoomedView) stub.inflate();
}
}
});
if (AppConstants.MOZ_MEDIA_PLAYER) {
// Check if the fragment is already added. This should never be true here, but this is
// a nice safety check.
// If casting is disabled, these classes aren't built. We use reflection to initialize them.
final Class<?> mediaManagerClass = getMediaPlayerManager();
if (mediaManagerClass != null) {
try {
final String tag = "";
mediaManagerClass.getDeclaredField("MEDIA_PLAYER_TAG").get(tag);
Log.i(LOGTAG, "Found tag " + tag);
final Fragment frag = getSupportFragmentManager().findFragmentByTag(tag);
if (frag == null) {
final Method getInstance = mediaManagerClass.getMethod("getInstance", (Class[]) null);
final Fragment mpm = (Fragment) getInstance.invoke(null);
getSupportFragmentManager().beginTransaction().disallowAddToBackStack().add(mpm, tag).commit();
}
} catch (Exception ex) {
Log.e(LOGTAG, "Error initializing media manager", ex);
}
}
}
if (AppConstants.MOZ_STUMBLER_BUILD_TIME_ENABLED && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
// Start (this acts as ping if started already) the stumbler lib; if the stumbler has queued data it will upload it.
// Stumbler operates on its own thread, and startup impact is further minimized by delaying work (such as upload) a few seconds.
// Avoid any potential startup CPU/thread contention by delaying the pref broadcast.
final long oneSecondInMillis = 1000;
ThreadUtils.getBackgroundHandler().postDelayed(new Runnable() {
@Override
public void run() {
GeckoPreferences.broadcastStumblerPref(BrowserApp.this);
}
}, oneSecondInMillis);
}
if (AppConstants.MOZ_ANDROID_DOWNLOAD_CONTENT_SERVICE) {
// TODO: Better scheduling of sync action (Bug 1257492)
DownloadContentService.startSync(this);
DownloadContentService.startVerification(this);
}
FeedService.setup(this);
super.handleMessage(event, message);
break;
case "Gecko:Ready":
// Handle this message in GeckoApp, but also enable the Settings
// menuitem, which is specific to BrowserApp.
super.handleMessage(event, message);
final Menu menu = mMenu;
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
if (menu != null) {
menu.findItem(R.id.settings).setEnabled(true);
menu.findItem(R.id.help).setEnabled(true);
}
}
});
// Display notification for Mozilla data reporting, if data should be collected.
if (AppConstants.MOZ_DATA_REPORTING && Restrictions.isAllowed(this, Restrictable.DATA_CHOICES)) {
DataReportingNotification.checkAndNotifyPolicy(GeckoAppShell.getContext());
}
break;
case "Search:Keyword":
storeSearchQuery(message.getString("query"));
recordSearch(GeckoSharedPrefs.forProfile(this), message.getString("identifier"),
TelemetryContract.Method.ACTIONBAR);
break;
case "LightweightTheme:Update":
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mDynamicToolbar.setVisible(true, VisibilityTransition.ANIMATE);
}
});
break;
case "Video:Play":
if (SwitchBoard.isInExperiment(this, Experiments.HLS_VIDEO_PLAYBACK)) {
final String uri = message.getString("uri");
final String uuid = message.getString("uuid");
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
mVideoPlayer.start(Uri.parse(uri));
Telemetry.sendUIEvent(TelemetryContract.Event.SHOW, TelemetryContract.Method.CONTENT, "playhls");
}
});
}
break;
case "Tab:Added":
if (message.getBoolean("cancelEditMode")) {
ThreadUtils.postToUiThread(new Runnable() {
@Override
public void run() {
// Set the target tab to null so it does not get selected (on editing
// mode exit) in lieu of the tab that we're going to open and select.
mTargetTabForEditingMode = null;
mBrowserToolbar.cancelEdit();
}
});
}
break;
default:
super.handleMessage(event, message);
break;
}
} catch (Exception e) {
Log.e(LOGTAG, "Exception handling message \"" + event + "\":", e);
}
}
@Override
public void addTab() {
Tabs.getInstance().addTab();
@ -3248,16 +3182,16 @@ public class BrowserApp extends GeckoApp
mMenu.removeItem(id);
}
private void updateAddonMenuItem(int id, JSONObject options) {
private void updateAddonMenuItem(int id, final GeckoBundle options) {
// Set attribute for the menu item in cache, if available
if (mAddonMenuItemsCache != null && !mAddonMenuItemsCache.isEmpty()) {
for (MenuItemInfo item : mAddonMenuItemsCache) {
if (item.id == id) {
item.label = options.optString("name", item.label);
item.checkable = options.optBoolean("checkable", item.checkable);
item.checked = options.optBoolean("checked", item.checked);
item.enabled = options.optBoolean("enabled", item.enabled);
item.visible = options.optBoolean("visible", item.visible);
item.label = options.getString("name", item.label);
item.checkable = options.getBoolean("checkable", item.checkable);
item.checked = options.getBoolean("checked", item.checked);
item.enabled = options.getBoolean("enabled", item.enabled);
item.visible = options.getBoolean("visible", item.visible);
item.added = (mMenu != null);
break;
}
@ -3270,11 +3204,11 @@ public class BrowserApp extends GeckoApp
final MenuItem menuItem = mMenu.findItem(id);
if (menuItem != null) {
menuItem.setTitle(options.optString("name", menuItem.getTitle().toString()));
menuItem.setCheckable(options.optBoolean("checkable", menuItem.isCheckable()));
menuItem.setChecked(options.optBoolean("checked", menuItem.isChecked()));
menuItem.setEnabled(options.optBoolean("enabled", menuItem.isEnabled()));
menuItem.setVisible(options.optBoolean("visible", menuItem.isVisible()));
menuItem.setTitle(options.getString("name", menuItem.getTitle().toString()));
menuItem.setCheckable(options.getBoolean("checkable", menuItem.isCheckable()));
menuItem.setChecked(options.getBoolean("checked", menuItem.isChecked()));
menuItem.setEnabled(options.getBoolean("enabled", menuItem.isEnabled()));
menuItem.setVisible(options.getBoolean("visible", menuItem.isVisible()));
}
}
@ -4029,11 +3963,6 @@ public class BrowserApp extends GeckoApp
});
}
private void resetFeedbackLaunchCount() {
SharedPreferences settings = getPreferences(Activity.MODE_PRIVATE);
settings.edit().putInt(getPackageName() + ".feedback_launch_count", 0).apply();
}
// HomePager.OnUrlOpenListener
@Override
public void onUrlOpen(String url, EnumSet<OnUrlOpenListener.Flags> flags) {
@ -4147,34 +4076,6 @@ public class BrowserApp extends GeckoApp
return mReadingListHelper;
}
/**
* Launch UI that lets the user update Firefox.
*
* This depends on the current channel: Release and Beta both direct to the
* Google Play Store. If updating is enabled, Aurora, Nightly, and custom
* builds open about:, which provides an update interface.
*
* If updating is not enabled, this simply logs an error.
*
* @return true if update UI was launched.
*/
protected boolean handleUpdaterLaunch() {
if (AppConstants.RELEASE_OR_BETA) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("market://details?id=" + getPackageName()));
startActivity(intent);
return true;
}
if (AppConstants.MOZ_UPDATER) {
Tabs.getInstance().loadUrlInTab(AboutPages.UPDATER);
return true;
}
Log.w(LOGTAG, "No candidate updater found; ignoring launch request.");
return false;
}
/* Implementing ActionModeCompat.Presenter */
@Override
public void startActionModeCompat(final ActionModeCompat.Callback callback) {

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше