Skip to content
Browse files

Initial commit

  • Loading branch information...
0 parents commit a0b5331fb183c697c9d50e91d4bf985cc6ff67bd @libc committed
Showing with 301 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +1 −0 CHANGELOG
  3. +21 −0 LICENSE
  4. +12 −0 Manifest
  5. +6 −0 README
  6. +17 −0 Rakefile
  7. +10 −0 lib/tidy_ffi.rb
  8. +71 −0 lib/tidy_ffi/interface.rb
  9. +37 −0 lib/tidy_ffi/lib_tidy.rb
  10. +20 −0 lib/tidy_ffi/tidy.rb
  11. +26 −0 lib/tidy_ffi/tidy_ffi_extensions.rb
  12. +12 −0 test/test_helper.rb
  13. +22 −0 test/test_simple.rb
  14. +44 −0 tidy_ffi.gemspec
2 .gitignore
@@ -0,0 +1,2 @@
+pkg/*.gem
+doc/*
1 CHANGELOG
@@ -0,0 +1 @@
+v0.0.0. Initial release.
21 LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2009 Eugene Pimenov
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
12 Manifest
@@ -0,0 +1,12 @@
+CHANGELOG
+LICENSE
+Manifest
+README
+Rakefile
+lib/tidy_ffi/interface.rb
+lib/tidy_ffi/lib_tidy.rb
+lib/tidy_ffi/tidy.rb
+lib/tidy_ffi/tidy_ffi_extensions.rb
+lib/tidy_ffi.rb
+test/test_helper.rb
+test/test_simple.rb
6 README
@@ -0,0 +1,6 @@
+=Tidy FFI
+==Purpose
+I wanna clean and simple tidy library. For example:
+ TidyFFI::Tidy.new('a string').clean
+
+For now it can't do anything else than clean :)
17 Rakefile
@@ -0,0 +1,17 @@
+require 'rubygems'
+begin
+ require 'echoe'
+ Echoe.new('tidy_ffi') do |p|
+ p.author = 'Eugene Pimenov'
+ p.summary = 'Tidy library interface via FFI'
+ p.url = 'http://github.com/libc/tidy_ffi'
+ p.runtime_dependencies = ['ffi >= 0.2.0']
+ p.development_dependencies = ['rr', 'matchy', 'context']
+ end
+rescue LoadError => boom
+ puts "You are missing a dependency required for meta-operations on this gem."
+ puts "#{boom.to_s.capitalize}."
+
+ desc 'No effect.'
+ task :default do; end
+end
10 lib/tidy_ffi.rb
@@ -0,0 +1,10 @@
+require 'rubygems'
+require 'ffi'
+
+module TidyFFI
+ self.autoload :LibTidy, 'tidy_ffi/lib_tidy'
+ self.autoload :Interface, 'tidy_ffi/interface'
+end
+
+require 'tidy_ffi/tidy'
+require 'tidy_ffi/tidy_ffi_extensions'
71 lib/tidy_ffi/interface.rb
@@ -0,0 +1,71 @@
+# Interface to libtidy.
+class TidyFFI::Interface
+ LibTidy = TidyFFI::LibTidy
+
+ # Returns a TidyFFI::Interface with initialized interface.
+ def self.with_doc
+ doc = LibTidy.tidyCreate
+ nd = new(doc)
+ nd.with_redirected_error_buffer { yield nd }
+ ensure
+ LibTidy.tidyRelease(doc)
+ end
+
+ def initialize(doc) #:nodoc:
+ @doc = doc
+ end
+
+ # Sets string to tidy
+ def string=(str)
+ LibTidy.tidyParseString(@doc, str)
+ end
+
+ # Cleans string
+ def clean
+ @output = nil
+ LibTidy.tidyCleanAndRepair(@doc)
+ end
+ alias :clean_and_repair :clean
+ alias :repair :clean
+
+ # Returns output from tidy library
+ def output
+ @output ||= begin
+ with_buffer_pointer do |buf|
+ LibTidy.tidySaveBuffer(@doc, buf)
+ buf[:bp]
+ end
+ end
+ end
+
+ # Redirects error buffer
+ def with_redirected_error_buffer
+ with_buffer_pointer do |buf|
+ @error_buffer = buf
+ LibTidy.tidySetErrorBuffer(@doc, buf)
+ yield
+ end
+ ensure
+ @error_buffer = nil
+ end
+
+ # Yields block with new buffer
+ def with_buffer_pointer
+ buf = tidy_buf_object.new
+ yield buf
+ ensure
+ LibTidy.tidyBufFree(buf)
+ end
+
+ def tidy_buf_object
+ @tidy_buf_object ||= begin
+ release_date = Date.parse(LibTidy.tidyReleaseDate) rescue nil
+ if release_date && (release_date > Date.parse("Dec 29 2006"))
+ TidyFFI::LibTidy::TidyBufWithAllocator
+ else
+ TidyFFI::LibTidy::TidyBuf
+ end
+ end
+ end
+ private :tidy_buf_object
+end
37 lib/tidy_ffi/lib_tidy.rb
@@ -0,0 +1,37 @@
+# This file must be lazy loaded!
+class TidyFFI::LibTidy #:nodoc:
+ extend FFI::Library
+ ffi_lib TidyFFI.library_path
+
+ attach_function :tidyReleaseDate, [], :string
+
+ attach_function :tidyCreate, [], :pointer
+ attach_function :tidyRelease, [:pointer], :void
+
+ attach_function :tidyCleanAndRepair, [:pointer], :int
+ attach_function :tidyRunDiagnostics, [:pointer], :int
+
+ attach_function :tidyParseString, [:pointer, :string], :int
+
+ attach_function :tidySaveBuffer, [:pointer, :pointer], :int
+
+ attach_function :tidySetErrorBuffer, [:pointer, :pointer], :int
+
+ attach_function :tidyBufFree, [:pointer], :void
+end
+
+class TidyFFI::LibTidy::TidyBuf < FFI::Struct #:nodoc:
+ layout :bp, :string,
+ :size, :uint,
+ :allocated, :uint,
+ :next, :uint
+end
+
+class TidyFFI::LibTidy::TidyBufWithAllocator < FFI::Struct #:nodoc:
+ layout :allocator, :pointer,
+ :bp, :string,
+ :size, :uint,
+ :allocated, :uint,
+ :next, :uint
+end
+
20 lib/tidy_ffi/tidy.rb
@@ -0,0 +1,20 @@
+class TidyFFI::Tidy
+ # Initialized object. str is a string to tidy, options is ignored for now :)
+ def initialize(str, options = {})
+ @string = str
+ parse_options(options)
+ end
+
+ # Returns cleaned string
+ def clean
+ @clean ||= TidyFFI::Interface.with_doc do |doc|
+ doc.string = @string
+ doc.clean
+ doc.output
+ end
+ end
+
+ def parse_options(options)
+ end
+ private :parse_options
+end
26 lib/tidy_ffi/tidy_ffi_extensions.rb
@@ -0,0 +1,26 @@
+module TidyFFI::TidyFFIExtensions #:nodoc:
+ # Sets path to libtidy.{dylib,so}
+ def library_path=(path)
+ @libtidy_path = path
+ end
+
+ # Returns path to libtidy.{dylib,so}
+ def library_path
+ @libtidy_path ||= find_tidy
+ end
+
+ def find_tidy
+ fnames = ['libtidy.dylib', 'libtidy.so']
+ pathes = []
+ pathes += ENV['LD_LIBRARY_PATH'].split(':') if ENV['LD_LIBRARY_PATH']
+ pathes += ENV['DYLD_LIBRARY_PATH'].split(':') if ENV['DYLD_LIBRARY_PATH']
+ pathes += ENV['PATH'].split(':').reject { |a| a['sbin'] }.map { |a| a.sub('/bin', '/lib') } if ENV['PATH']
+ pathes = ['/usr/lib', '/usr/local/lib'] if pathes.size == 0
+ for path in pathes.uniq
+ fnames.each { |fname| return File.join(path, fname) if File.exists?(File.join(path, fname)) }
+ end
+ nil
+ end
+ private :find_tidy
+end
+TidyFFI.extend TidyFFI::TidyFFIExtensions
12 test/test_helper.rb
@@ -0,0 +1,12 @@
+require 'test/unit'
+
+require 'tidy_ffi'
+
+require 'rubygems'
+require 'rr'
+require 'matchy'
+require 'context'
+
+class Test::Unit::TestCase
+ alias method_name name unless instance_methods.include?('method_name')
+end
22 test/test_simple.rb
@@ -0,0 +1,22 @@
+require File.join(File.dirname(__FILE__), 'test_helper')
+
+class TestSimple < Test::Unit::TestCase
+ T = TidyFFI::Tidy
+ context "TidyFFI::Tidy" do
+ context "public interface" do
+ [[:initialize, -2],
+ [:clean, 0]].each do |method, arity|
+ it "method #{method} has arity #{arity}" do
+ T.instance_method(method).arity.should == arity
+ end
+ end
+ end
+
+ context "simple cleanup" do
+ it "clean up text" do
+ T.new("test").clean.should =~ %r{<body>\s+test\s+</body>}
+ T.new("test").clean.should =~ %r{<meta name="generator" content=.+?Tidy.+?>}m
+ end
+ end
+ end
+end
44 tidy_ffi.gemspec
@@ -0,0 +1,44 @@
+# -*- encoding: utf-8 -*-
+
+Gem::Specification.new do |s|
+ s.name = %q{tidy_ffi}
+ s.version = "0.0.0"
+
+ s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
+ s.authors = ["Eugene Pimenov"]
+ s.date = %q{2009-02-12}
+ s.description = %q{Tidy library interface via FFI}
+ s.email = %q{}
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "lib/tidy_ffi/interface.rb", "lib/tidy_ffi/lib_tidy.rb", "lib/tidy_ffi/tidy.rb", "lib/tidy_ffi/tidy_ffi_extensions.rb", "lib/tidy_ffi.rb"]
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "lib/tidy_ffi/interface.rb", "lib/tidy_ffi/lib_tidy.rb", "lib/tidy_ffi/tidy.rb", "lib/tidy_ffi/tidy_ffi_extensions.rb", "lib/tidy_ffi.rb", "test/test_helper.rb", "test/test_simple.rb", "tidy_ffi.gemspec"]
+ s.has_rdoc = true
+ s.homepage = %q{http://github.com/libc/tidy_ffi}
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tidy_ffi", "--main", "README"]
+ s.require_paths = ["lib"]
+ s.rubyforge_project = %q{tidy_ffi}
+ s.rubygems_version = %q{1.3.1}
+ s.summary = %q{Tidy library interface via FFI}
+ s.test_files = ["test/test_helper.rb", "test/test_simple.rb"]
+
+ if s.respond_to? :specification_version then
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
+ s.specification_version = 2
+
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
+ s.add_runtime_dependency(%q<ffi>, [">= 0", "= 0.2.0"])
+ s.add_development_dependency(%q<rr>, [">= 0"])
+ s.add_development_dependency(%q<matchy>, [">= 0"])
+ s.add_development_dependency(%q<context>, [">= 0"])
+ else
+ s.add_dependency(%q<ffi>, [">= 0", "= 0.2.0"])
+ s.add_dependency(%q<rr>, [">= 0"])
+ s.add_dependency(%q<matchy>, [">= 0"])
+ s.add_dependency(%q<context>, [">= 0"])
+ end
+ else
+ s.add_dependency(%q<ffi>, [">= 0", "= 0.2.0"])
+ s.add_dependency(%q<rr>, [">= 0"])
+ s.add_dependency(%q<matchy>, [">= 0"])
+ s.add_dependency(%q<context>, [">= 0"])
+ end
+end

0 comments on commit a0b5331

Please sign in to comment.
Something went wrong with that request. Please try again.