-- Copyright 2020 United States Government as represented by the Administrator -- of the National Aeronautics and Space Administration. All Rights Reserved. -- -- Disclaimers -- -- No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY -- OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT -- LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO -- SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -- PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE -- SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF -- PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN -- ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR -- RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR -- ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, -- GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING -- THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES -- IT "AS IS." -- -- Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST -- THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS -- ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN -- ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH USE, -- INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S -- USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE -- UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY -- PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY -- FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS -- AGREEMENT. -- -- | Auxiliary functions for working with values of type 'String'. module Data.String.Extra ( -- * Safe I/O safeReadFile -- * String sanitization , sanitizeLCIdentifier , sanitizeUCIdentifier ) where -- External imports import Control.Exception ( catch ) import Data.Char ( toLower, toUpper ) import System.IO.Error ( isDoesNotExistError ) -- * Safe I/O -- | Safely read a file into a 'String', returning a 'Left' error message if -- the file cannot be opened. -- This function could also be placed in System.IO. However, we decide to -- include it in this module for symmetry with an analogous function for -- ByteString, included in Data.ByteString.Extra. safeReadFile :: FilePath -> IO (Either String String) safeReadFile :: String -> IO (Either String String) safeReadFile String fp = forall e a. Exception e => IO a -> (e -> IO a) -> IO a catch (forall (m :: * -> *) a. Monad m => a -> m a return forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b <$> String -> IO String readFile String fp) forall a b. (a -> b) -> a -> b $ \IOError e -> if IOError -> Bool isDoesNotExistError IOError e then forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. a -> Either a b Left forall a b. (a -> b) -> a -> b $ String -> String strStringFileNotFound String fp else forall (m :: * -> *) a. Monad m => a -> m a return forall a b. (a -> b) -> a -> b $ forall a b. a -> Either a b Left forall a b. (a -> b) -> a -> b $ String -> String strStringCannotOpenFile String fp -- ** Error messages -- | File-not-found message. strStringFileNotFound :: FilePath -> String strStringFileNotFound :: String -> String strStringFileNotFound String fp = String "File not found: " forall a. [a] -> [a] -> [a] ++ String fp -- | Cannot-open-file message. strStringCannotOpenFile :: FilePath -> String strStringCannotOpenFile :: String -> String strStringCannotOpenFile String fp = String "Error opening file: " forall a. [a] -> [a] -> [a] ++ String fp -- * Sanitization -- | Remove extraneous characters from an identifier and make the starting -- character lowercase. -- -- This function currently replaces hyphens with underscores. sanitizeLCIdentifier :: String -> String sanitizeLCIdentifier :: String -> String sanitizeLCIdentifier = String -> String headToLower forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a -> b) -> [a] -> [b] map Char -> Char sanitizeCharacter where sanitizeCharacter :: Char -> Char sanitizeCharacter Char '-' = Char '_' sanitizeCharacter Char x = Char x headToLower :: [Char] -> [Char] headToLower :: String -> String headToLower [] = [] headToLower (Char x:String xs) = Char -> Char toLower Char x forall a. a -> [a] -> [a] : String xs -- | Remove extraneous characters from an identifier and make the starting -- character uppercase. -- -- This function currently replaces hyphens with underscores. sanitizeUCIdentifier :: String -> String sanitizeUCIdentifier :: String -> String sanitizeUCIdentifier = String -> String headToUpper forall b c a. (b -> c) -> (a -> b) -> a -> c . forall a b. (a -> b) -> [a] -> [b] map Char -> Char sanitizeCharacter where sanitizeCharacter :: Char -> Char sanitizeCharacter Char '-' = Char '_' sanitizeCharacter Char x = Char x headToUpper :: [Char] -> [Char] headToUpper :: String -> String headToUpper [] = [] headToUpper (Char x:String xs) = Char -> Char toUpper Char x forall a. a -> [a] -> [a] : String xs