正規表現

Ruby ライクな正規表現クラスを作り始めてみる。

package ryugate.text

import java.util.regex.Pattern
import java.util.regex.Matcher

class Regexp(ptn:Pattern) {
  def this(str:String) = this(Pattern.compile(str))
  
  def re_match(str:String):Matcher = {
      val md = ptn.matcher(str)
      if (md.matches) md else null
  }
}

使うときには

val str = "/123"
val md = new Regexp("\\/([0-9]+)").re_match(str)

のようになる。


しかし、 正規表現リテラルが無いだけで、
急に(ライトウェイトでないと言う意味で)ヘビーな言語に見えてくる。


「どう書く.org」にimplicitを使って
既存のクラスを拡張(したのと同じ効果を出す)方法
(http://ja.doukaku.org/51/lang/scala/)
が乗っていたので、
次はそいつを利用してみる予定。


ついでに(というか、正規表現に手を付けたのもこっちがきっかけだが)
httpdサーバのテストプログラムを改良して、
URLによっては画像を返すようにしてみた。

import java.io.PrintWriter

import javax.servlet.http.HttpServlet
import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

import org.mortbay.jetty.Connector
import org.mortbay.jetty.Server
import org.mortbay.jetty.nio.SelectChannelConnector

import org.mortbay.jetty.servlet.ServletHandler
import org.mortbay.jetty.NCSARequestLog
import org.mortbay.jetty.handler.RequestLogHandler

import org.apache.velocity.app.Velocity;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.Template;

import java.awt.Font
import java.awt.Color
import java.awt.GraphicsEnvironment
import javax.imageio.ImageIO

import ryugate.image._
import ryugate.video._
import ryugate.text._

//------------------------------------
class ServletServer extends HttpServlet {
  override protected def doGet(request:HttpServletRequest, response:HttpServletResponse) {
    common(request, response)
  }
  override protected def doPost(request:HttpServletRequest, response:HttpServletResponse) {
    common(request, response)
  }
  override protected def doPut(request:HttpServletRequest, response:HttpServletResponse) {
    common(request, response)
  }
  override protected def doDelete(request:HttpServletRequest, response:HttpServletResponse) {
    common(request, response)
  }

  //------------------------------------
  def common(request:HttpServletRequest, response:HttpServletResponse) {
    val md = new Regexp("\\/([0-9]+)").re_match(request.getPathInfo)
    if (md != null) {
      val outstream = response.getOutputStream
      response.setContentType("image/png")
      ImageIO.write(make_image(md.group(1).toInt, 5).image, "png", outstream)
    } else {
      val outwriter = response.getWriter
      val context = makeContext
      context.put("request", request)
      context.put("body", read_body(request))
      response.setContentType("text/html")
      Velocity.getTemplate("example.vm").merge(context, outwriter);
    }
  }

  //------------------------------------
  def read_body(request:HttpServletRequest) = {
    val reader = request.getReader
    var body = ""
    var line = reader.readLine
    while(line != null) {
      body += line
      body += "\n"
      line = reader.readLine
    }
    reader.close
    body
  }

  //------------------------------------
  def make_image(no:int, r:int) = {
    val img = new Image(400,300, Image.TYPE_INT_RGB)
    img.clearBackground(Color.BLUE)
    img.process{g => 
      g.setFont("MS Gothic", Font.BOLD, 48)
      g.antialias{g =>
        g.drawString(new Timecode(no).tc(r).toString, 50,100)
        g.drawString(Format.sprintf("%04d", no), 50,150)
      }
    }
  }
  
  //------------------------------------
  def makeContext() = {
    val context = new VelocityContext();
      
    context.put("array1", Array("10","20"))

    val ar = Array("10","20")
    context.put("array1", ar)

    val lst = List("30","40")
    context.put("list1", lst.toArray)

    val ar2 = lst.toArray
    context.put("array2", ar2)

    context
  }
}

//------------------------------------
object httpd extends Application {
  Velocity.init("velocity.properties");

  //------------------------------------
  val server            = new Server
  val connector         = new SelectChannelConnector
  val requestLog        = new NCSARequestLog
  val requestLogHandler = new RequestLogHandler
  connector.setPort(8080)
  server.addConnector(connector)
  requestLog.setExtended(false)
  requestLogHandler.setRequestLog(requestLog)
  server.addHandler(requestLogHandler)

  //------------------------------------
  val servletHandler    = new ServletHandler
  servletHandler.addServletWithMapping(classOf[ServletServer], "/hoge/*")
  server.addHandler(servletHandler)

  //------------------------------------
  server.start
  server.join
}