Hatena::Groupmoz-addon

Ci.nsIZIGOROu

2008-03-12グリス

nsIURLParserを使ったURLの展開とプリミティブ型の引数での参照渡し

| 02:20 |  nsIURLParserを使ったURLの展開とプリミティブ型の引数での参照渡し - Ci.nsIZIGOROu を含むブックマーク はてなブックマーク -  nsIURLParserを使ったURLの展開とプリミティブ型の引数での参照渡し - Ci.nsIZIGOROu

nsIURLParserについて

topgarciniacambogiareviews.com

を見ると分かるよ。

まぁ典型的なparserです。

プリミティブ型の引数での参照渡し

void parsePath ( char* path , PRInt32 pathLen , out PRUint32 filepathPos , out PRInt32 filepathLen , out PRUint32 paramPos , out PRInt32 paramLen , out PRUint32 queryPos , out PRInt32 queryLen , out PRUint32 refPos , out PRInt32 refLen )

まぁこんな感じでoutな引数でプリミティブ型だと参照渡しは出来ませんので、そういう場合はObject型の変数にvalueと言うプロパティを付けて渡します。

var filepathPos = {value: null};

みたいな感じ。

とするとXPConnect側で上手い事やってくれます。

戻り値としてはvalueプロパティを見るだけで良い次第でございます。

ソース1 (全然DRYじゃない書き方)

gdgdですので、こちらはスルーの方向で。

t

ソース2 (改良版)

ちょっとだけ改良。もっと奇麗に書ける様になりたい><

var URLParser = function() {
};

URLParser.prototype = {
  parser: Cc["@mozilla.org/network/url-parser;1?auth=maybe"].getService(Ci.nsIURLParser),
  parse: function(url) {
    var result = {url: url};

    this._parseSection(result, "URL", ["schemePos", "schemeLen", "authorityPos", "authorityLen", "pathPos", "pathLen"]);
    this._parseSection(result, "Authority", ["usernamePos", "usernameLen", "passwordPos", "passwordLen", "hostnamePos", "hostnameLen", "port"]);
    this._parseSection(result, "Path", ["filepathPos", "filepathLen", "paramPos", "paramLen", "queryPos", "queryLen", "refPos", "refLen"]);
    this._parseSection(result, "FilePath", ["directoryPos", "directoryLen", "basenamePos", "basenameLen", "extensionPos", "extensionLen"]);

    return result;
  },
  _parseSection: function(result, section, extraArgs) {
    var lc_section = section.toLowerCase();
    var leafs = [];
    
    for (var i = 1; i < extraArgs.length; i += 2) {
      leafs.push(extraArgs[i].substr(0, extraArgs[i].length - 3));
    }

    var methodName = "parse" + section;
    var target = result[lc_section];

    var outvals = this._callMethod(methodName, target, extraArgs);
    leafs.forEach(function(item) {
      result[item] = target.substr(outvals[item + "Pos"], outvals[item + "Len"]);
    });

    if (extraArgs.length % 2 == 1) {
      with ({ directVal: extraArgs[extraArgs.length - 1] }) {
        result[directVal] = (outvals[directVal] != -1) ? outvals[directVal] : undefined;
      }
    }
  },
  _callMethod: function(methodName, target, extraArgs) {
    var args = [target, target.length];
    var outVals = {};

    extraArgs.forEach(function(item) {
      args.push(outVals[item] = { value: null });
    });

    this.parser[methodName].apply(this.parser, args);

    var result = {};

    extraArgs.forEach(function(item) {
      result[item] = outVals[item].value;
    });

    return result;
  }
};

実行例

repl.inspect()してみた結果。

// http://zigorou:hogehoge@www.google.co.jp:8080/foo/bar/hoge.js;aaa?foo=bar#hoge
<object>.scheme=http
<object>.authority=zigorou:hogehoge@www.google.co.jp:8080
<object>.path=/foo/bar/hoge.js;aaa?foo=bar#hoge
<object>.username=zigorou
<object>.password=hogehoge
<object>.hostname=www.google.co.jp
<object>.port=8080
<object>.filepath=/foo/bar/hoge.js
<object>.param=aaa
<object>.query=foo=bar
<object>.ref=hoge
<object>.directory=/foo/bar/
<object>.basename=hoge
<object>.extension=js                            

今の拡張スクリプトを晒す

| 15:28 |  今の拡張スクリプトを晒す - Ci.nsIZIGOROu を含むブックマーク はてなブックマーク -  今の拡張スクリプトを晒す - Ci.nsIZIGOROu

/**
 * browser startup service utility
 */
var browser = {
  startUpService: Components.classes["@mozilla.org/toolkit/app-startup;1"].getService(Components.interfaces.nsIAppStartup),
  restart: function() {
    this.startUpService.quit(Components.interfaces.nsIAppStartup.eForceQuit | Components.interfaces.nsIAppStartup.eRestart); 
  },
  stop: function() {
    this.startUpService.quit(Components.interfaces.nsIAppStartup.eForceQuit); 
  }
}

/**
 * Open document for component from xulplanet.com
 */
function docForComponent(comp) {
    if (comp instanceof this.Ci.nsIJSCID) {
        comp = comp.toString();
    }

    if (!comp || !comp.match(/^@mozilla.org/)) {
        return;
    }

    var window = this.Cc["@mozilla.org/appshell/window-mediator;1"].getService(this.Ci.nsIWindowMediator).getMostRecentWindow("");
    var url = "http://www.xulplanet.com/references/xpcomref/comps/c_" + comp.replace("@mozilla.org", "").replace(/[¥/¥-¥?¥;¥=]/g, "") + ".html";

    window.getBrowser().addTab(url);
}

function docForInterface(iface, methodName) {
  if (iface instanceof this.Ci.nsISupports) {
    iface = iface.toString();
  }

  var window = repl.Cc["@mozilla.org/appshell/window-mediator;1"].getService(repl.Ci.nsIWindowMediator).getMostRecentWindow("");
  var url = "http://www.xulplanet.com/references/xpcomref/ifaces/" + iface + ".html";

  if (methodName) {
    url += "#method_" + methodName;
  }

  window.getBrowser().addTab(url);
}

function getInterfaceInfoByInterface(iface) {
  if (iface instanceof this.Ci.nsISupports) {
    iface = iface.toString();
  }

  var iinfo = this.Cc["@mozilla.org/scriptableInterfaceInfo;1"].createInstance(this.Ci.nsIScriptableInterfaceInfo);
  iinfo.initWithName(iface);

  return iinfo;
}

function getInterfacesByObject(obj, excludeSupports) {
  if (!excludeSupports) {
    excludeSupports = true;
  }

  var ifaces = [];

  for (var iface in this.Ci) {
    if (obj instanceof this.Ci[iface]) {
      if (excludeSupports && iface == "nsISupports") {
        continue;
      }

      ifaces.push(this.Ci[iface]);
    }
  }

  return ifaces;
}