Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix SEGFAULT and space leak #1

Merged
merged 8 commits into from

2 participants

@meteficha

Thanks! =)

@meteficha

Please let me know if you'd prefer that I released the updated version to Hackage myself. I'm not in a hurry, but you may have lost interest in this library since it's been 2.5 years since the last release =).

@meteficha

(Added more fixes to this pull request.)

@jamessanders jamessanders merged commit c6c2428 into jamessanders:master
@meteficha

Amazing, thanks! =)

@jamessanders

Thanks for the fixes, a new version has been uploaded to Hackage.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jan 10, 2013
  1. @meteficha

    Whitespace.

    meteficha authored
  2. @meteficha
  3. @meteficha

    .gitignore

    meteficha authored
  4. @meteficha

    Do not leak QR codes.

    meteficha authored
  5. @meteficha

    Bump version to 1.0.4.

    meteficha authored
Commits on Jan 14, 2013
  1. @meteficha

    Add GitHub to .cabal file.

    meteficha authored
Commits on Jan 17, 2013
  1. @meteficha
  2. @meteficha

    Better toMatrix performance.

    meteficha authored
This page is out of date. Refresh to see the latest.
Showing with 48 additions and 34 deletions.
  1. +2 −1  .gitignore
  2. +8 −4 haskell-qrencode.cabal
  3. +38 −29 src/Data/QRCode.hsc
View
3  .gitignore
@@ -1 +1,2 @@
-dist/
+*~
+dist*/
View
12 haskell-qrencode.cabal
@@ -1,10 +1,10 @@
Name: haskell-qrencode
-Version: 1.0.3
+Version: 1.0.4
Synopsis: Haskell bindings for libqrencode.
Description: Haskell bindings for libqrencode.
- Libqrencode is a C library for encoding data in a QR Code symbol, a kind of 2D symbology
- that can be scanned by handy terminals such as a mobile phone with CCD. The capacity of
+ Libqrencode is a C library for encoding data in a QR Code symbol, a kind of 2D symbology
+ that can be scanned by handy terminals such as a mobile phone with CCD. The capacity of
QR Code is up to 7000 digits or 4000 characters, and is highly robust.
License: BSD3
@@ -13,8 +13,12 @@ Author: James Sanders
Maintainer: james.sanders@thisismedium.com
Category: Data
Build-type: Simple
-Cabal-version: >=1.2
+Cabal-version: >=1.6
+Homepage: https://github.com/jamessanders/haskell-qrencode
+Source-repository head
+ type: git
+ location: git://github.com/jamessanders/haskell-qrencode.git
Library
hs-source-dirs: src
View
67 src/Data/QRCode.hsc
@@ -2,33 +2,34 @@
-- | Haskell bindings for libqrencode. <http://fukuchi.org/works/qrencode/index.en.html>
--
--- Libqrencode is a C library for encoding data in a QR Code symbol, a kind of 2D symbology
--- that can be scanned by handy terminals such as a mobile phone with CCD. The capacity of
+-- Libqrencode is a C library for encoding data in a QR Code symbol, a kind of 2D symbology
+-- that can be scanned by handy terminals such as a mobile phone with CCD. The capacity of
-- QR Code is up to 7000 digits or 4000 characters, and is highly robust.
-module Data.QRCode (encodeByteString,
+module Data.QRCode (encodeByteString,
encodeString,
getQRCodeVersion,
getQRCodeWidth,
getQRCodeString,
toMatrix,
- QREncodeLevel (..),
+ QREncodeLevel (..),
QREncodeMode (..)) where
import Control.Monad
-import Data.ByteString (ByteString, unpack, useAsCString, packCString)
+import Data.ByteString (ByteString, unpack, useAsCString, packCStringLen)
import qualified Data.ByteString as BS
import Data.Maybe
import Foreign
+import Foreign.C.Error
import Foreign.C.String
import Foreign.C.Types
import Foreign.Storable
#include <qrencode.h>
-data QREncodeLevel = QR_ECLEVEL_L
- | QR_ECLEVEL_M
- | QR_ECLEVEL_Q
+data QREncodeLevel = QR_ECLEVEL_L
+ | QR_ECLEVEL_M
+ | QR_ECLEVEL_Q
| QR_ECLEVEL_H
data QREncodeMode = QR_MODE_NUM -- ^ Numeric mode
@@ -43,12 +44,12 @@ convertQREncodeLevel QR_ECLEVEL_Q = #const QR_ECLEVEL_Q
convertQREncodeLevel QR_ECLEVEL_H = #const QR_ECLEVEL_H
convertQREncodeMode :: QREncodeMode -> CInt
-convertQREncodeMode QR_MODE_NUM = #const QR_MODE_NUM
-convertQREncodeMode QR_MODE_AN = #const QR_MODE_AN
-convertQREncodeMode QR_MODE_EIGHT = #const QR_MODE_8
-convertQREncodeMode QR_MODE_KANJI = #const QR_MODE_KANJI
+convertQREncodeMode QR_MODE_NUM = #const QR_MODE_NUM
+convertQREncodeMode QR_MODE_AN = #const QR_MODE_AN
+convertQREncodeMode QR_MODE_EIGHT = #const QR_MODE_8
+convertQREncodeMode QR_MODE_KANJI = #const QR_MODE_KANJI
-data QRcode = QRcode {
+data QRcode = QRcode {
getQRCodeVersion :: Int,
getQRCodeWidth :: Int,
getQRCodeString :: ByteString
@@ -80,7 +81,7 @@ instance Storable QRcodeStruct where
#{poke QRcode, data} ptr data'
-foreign import ccall unsafe "QRcode_encodeString"
+foreign import ccall safe "QRcode_encodeString"
c_encodeString :: CString -- string
-> CInt -- version
-> CInt -- level
@@ -88,15 +89,19 @@ foreign import ccall unsafe "QRcode_encodeString"
-> CInt -- casesensitive
-> IO (Ptr QRcodeStruct)
+foreign import ccall unsafe "QRcode_free"
+ c_free :: Ptr QRcodeStruct
+ -> IO ()
+
-- | create a QR code from a ByteString
encodeByteString :: ByteString -- ^ String to encode
-> Maybe Int -- ^ Version (auto if Nothing)
-> QREncodeLevel -- ^ Encode Level
-> QREncodeMode -- ^ Encode Mode
-> Bool -- ^ Case-sensative
- -> IO QRcode
+ -> IO QRcode
encodeByteString str version level mode casesensitive = do
- when (BS.null str) $ error "empty bytestring provided"
+ when (BS.null str) $ error "empty bytestring provided"
useAsCString str $ \s-> encoder s version level mode casesensitive
-- | create a QR code from a String
@@ -107,28 +112,32 @@ encodeString :: String -- ^ String to encode
-> Bool -- ^ Case-sensative
-> IO QRcode
encodeString str version level mode casesensitive = do
- when (null str) $ error "empty string provided"
+ when (null str) $ error "empty string provided"
newCAString str >>= \s-> encoder s version level mode casesensitive
-
+
encoder :: CString -> Maybe Int -> QREncodeLevel -> QREncodeMode -> Bool -> IO QRcode
encoder cstr ver level mode casesensitive = do
let l = convertQREncodeLevel level
let m = convertQREncodeMode mode
- c_qr <- join $ fmap peek $ c_encodeString cstr (fromIntegral $ fromMaybe 0 ver) l m (b2i casesensitive)
- let version = fromIntegral (c_version c_qr)
- let width = fromIntegral (c_width c_qr)
- str <- packCString (c_data c_qr)
- return (QRcode version width str)
+ c_qrptr <- throwErrnoIfNull "haskell-qrencode/QRcode_encodeString" $
+ c_encodeString cstr (fromIntegral $ fromMaybe 0 ver) l m (b2i casesensitive)
+ c_qr <- peek c_qrptr
+ let version = fromIntegral (c_version c_qr)
+ let width = fromIntegral (c_width c_qr)
+ str <- packCStringLen (c_data c_qr, width * width)
+ c_free c_qrptr
+ return (QRcode version width str)
where
- b2i True = 1
- b2i False = 0
+ b2i True = 1
+ b2i False = 0
-- | Convert a QRcode to a matrix of ones and zeros (1 = On, 0 = Off)
toMatrix :: QRcode -> [[Word8]]
-toMatrix (QRcode _ width str) =
+toMatrix (QRcode _ width str) =
regroup . map tobin . unpack $ str
where
- tobin c = c .&. 1
- regroup [] = []
- regroup x = take width x : regroup (drop width x)
+ tobin c = c .&. 1
+ regroup [] = []
+ regroup xs = let ~(this, rest) = splitAt width xs
+ in this : regroup rest
Something went wrong with that request. Please try again.