File manipulations (create, read, write, etc.)

Introduced classes

class FileReader

core :: FileReader

Stream that can read from a File
class FileStat

core :: FileStat

Information on a file
abstract class FileStream

core :: FileStream

Stream used to interact with a File or FileDescriptor
class FileWriter

core :: FileWriter

Stream that can write to a File
class Path

core :: Path

Utility class to access file system services.
class Stderr

core :: Stderr

Standard error stream.
class Stdin

core :: Stdin

Standard input stream.
class Stdout

core :: Stdout

Standard output stream.

Redefined classes

redef extern class CString

core :: file $ CString

C string char *
redef abstract class FlatString

core :: file $ FlatString

Immutable strings of characters.
redef enum Int

core :: file $ Int

Native integer numbers.
redef class Sys

core :: file $ Sys

The main class of the program.
redef abstract class Text

core :: file $ Text

High-level abstraction for all text representations
redef interface Writable

core :: file $ Writable

Things that can be efficienlty written to a Writer

All class definitions

redef extern class CString

core :: file $ CString

C string char *
class FileReader

core $ FileReader

Stream that can read from a File
class FileStat

core $ FileStat

Information on a file
abstract class FileStream

core $ FileStream

Stream used to interact with a File or FileDescriptor
class FileWriter

core $ FileWriter

Stream that can write to a File
redef abstract class FlatString

core :: file $ FlatString

Immutable strings of characters.
redef enum Int

core :: file $ Int

Native integer numbers.
class Path

core $ Path

Utility class to access file system services.
class Stderr

core $ Stderr

Standard error stream.
class Stdin

core $ Stdin

Standard input stream.
class Stdout

core $ Stdout

Standard output stream.
redef class Sys

core :: file $ Sys

The main class of the program.
redef abstract class Text

core :: file $ Text

High-level abstraction for all text representations
redef interface Writable

core :: file $ Writable

Things that can be efficienlty written to a Writer
package_diagram core::file file core::time time core::file->core::time core::gc gc core::file->core::gc core::stream stream core::time->core::stream core::kernel kernel core::gc->core::kernel ...core::stream ... ...core::stream->core::stream ...core::kernel ... ...core::kernel->core::kernel core::environ environ core::environ->core::file core::exec exec core::exec->core::file core::core core core::core->core::environ core::core->core::exec core::core... ... core::core...->core::core

Ancestors

module abstract_collection

core :: abstract_collection

Abstract collection classes and services.
module abstract_text

core :: abstract_text

Abstract class for manipulation of sequences of characters
module array

core :: array

This module introduces the standard array structure.
module bytes

core :: bytes

Services for byte streams and arrays
module circular_array

core :: circular_array

Efficient data structure to access both end of the sequence.
module codec_base

core :: codec_base

Base for codecs to use with streams
module codecs

core :: codecs

Group module for all codec-related manipulations
module collection

core :: collection

This module define several collection classes.
module error

core :: error

Standard error-management infrastructure.
module fixed_ints

core :: fixed_ints

Basic integers of fixed-precision
module fixed_ints_text

core :: fixed_ints_text

Text services to complement fixed_ints
module flat

core :: flat

All the array-based text representations
module hash_collection

core :: hash_collection

Introduce HashMap and HashSet.
module iso8859_1

core :: iso8859_1

Codec for ISO8859-1 I/O
module kernel

core :: kernel

Most basic classes and methods.
module list

core :: list

This module handle double linked lists
module math

core :: math

Mathematical operations
module native

core :: native

Native structures for text and bytes
module range

core :: range

Module for range of discrete objects.
module ropes

core :: ropes

Tree-based representation of a String.
module sorter

core :: sorter

This module contains classes used to compare things and sorts arrays.
module stream

core :: stream

Input and output streams of characters
module text

core :: text

All the classes and methods related to the manipulation of text entities
module union_find

core :: union_find

union–find algorithm using an efficient disjoint-set data structure
module utf8

core :: utf8

Codec for UTF-8 I/O

Parents

module gc

core :: gc

Access to the Nit internal garbage collection mechanism
module time

core :: time

Management of time and dates

Children

module environ

core :: environ

Access to the environment variables of the process
module exec

core :: exec

Invocation and management of operating system sub-processes.

Descendants

module a_star

a_star :: a_star

A* pathfinding in graphs
module a_star-m

a_star-m

module abstract_tree

trees :: abstract_tree

Introduce tree structures abstraction
module activities

android :: activities

Android Activities wrapper
module actors

actors :: actors

Abstraction of the actors concepts
module agent_simulation

actors :: agent_simulation

a "Framework" to make Multi-Agent Simulations in Nit
module ai

ai :: ai

Simple toolkit for artificial intelligence.
module all

sdl2 :: all

Unites the main sdl2 module and its sister library sdl2::image
module android

android :: android

Android services and implementation of app.nit
module android19

gamnit :: android19

Variation using features from Android API 19
module angles

geometry :: angles

Angle related service using Float to represent an angle in radians
module api

github :: api

Nit object oriented interface to Github api.
module app

ios :: app

Basic structure for Nit apps on iOS
module app

app :: app

app.nit is a framework to create cross-platform applications
module app_base

app :: app_base

Base of the app.nit framework, defines App
module app_kit

cocoa :: app_kit

The Application Kit provides services to create GUI
module array_debug

array_debug :: array_debug

Exposes functions to help profile or debug Arrays.
module assets

android :: assets

Implementation of app::assets
module assets

app :: assets

Portable services to load resources from the assets folder
module assets

ios :: assets

Implementation of app::assets
module assets_and_resources

android :: assets_and_resources

Android Assets and Resources Management
module at_boot

android :: at_boot

Import this module to launch Service at device boot
module attributes

sax :: attributes

Interface for a list of XML attributes.
module attributes_impl

sax :: attributes_impl

Default implementation of the Attributes interface.
module audio

app :: audio

Services to load and play Sound and Music from the assets folder
module audio

android :: audio

Android audio services, wraps a part of android audio API
module audio

linux :: audio

app::audio implementation for GNU/Linux using SDL2 mixer
module audio

ios :: audio

iOS implementation of app::audio using AVAudioPlayer
module aware

android :: aware

Android compatibility module
module backtrack

ai :: backtrack

Basic framework for active backtrack solver
module base64

base64 :: base64

Offers the base 64 encoding and decoding algorithms
module basic_ciphers

crypto :: basic_ciphers

Basic cryptographic ciphers and utilities.
module bcm2835

bcm2835 :: bcm2835

Services to control the bcm2835 chipset used in the Raspberry Pi
module binary

binary :: binary

Read and write binary data with any Reader and Writer
module bintree

trees :: bintree

Binary Tree data-structure
module bitmap

bitmap :: bitmap

The Bitmap class represents a 24-bit bitmap image. An instance can be constructed
module bktree

trees :: bktree

Implementation of BKTree
module bmfont

gamnit :: bmfont

Parse Angel Code BMFont format and draw text
module bootstrap

html :: bootstrap

HTML templates for Bootstrap components.
module boxes

geometry :: boxes

Provides interfaces and classes to represent basic geometry needs.
module bucketed_game

bucketed_game :: bucketed_game

Game framework with an emphasis on efficient event coordination
module bundle

android :: bundle

A mapping class of String to various value types used by the
module bytes

crypto :: bytes

Mix of utilities and services related to bytes
module c

c :: c

Structures and services for compatibility with the C language
module cache

github :: cache

Enable caching on Github API accesses.
module caching

serialization :: caching

Services for caching serialization engines
module camera_control

gamnit :: camera_control

Simple camera control for user, as the method accept_scroll_and_zoom
module camera_control_android

gamnit :: camera_control_android

Two fingers camera manipulation, pinch to zoom and slide to scroll
module camera_control_linux

gamnit :: camera_control_linux

Mouse wheel and middle mouse button to control camera
module cameras

gamnit :: cameras

Camera services producing Model-View-Projection matrices
module cameras_cache

gamnit :: cameras_cache

Cache the Matrix produced by Camera::mvp_matrix
module cardboard

gamnit :: cardboard

Update the orientation of world_camera at each frame using the head position given by android::cardboard
module cardboard

android :: cardboard

Services from the Google Cardboard SDK for virtual reality on Android
module cartesian

cartesian :: cartesian

Memory-efficient Cartesian products on heterogeneous collections.
module chameneosredux

actors :: chameneosredux

Example implemented from "The computer Language Benchmarks Game" - Chameneos-Redux
module checker

dom :: checker

Simple XML validity checker using the dom module
module client

gamnit :: client

Client-side network services for games and such
module clusters

dot :: clusters

Example from http://www.graphviz.org/content/cluster
module cocoa

cocoa :: cocoa

Cocoa API, the development layer of OS X
module cocoa_extern_types

cocoa :: cocoa_extern_types

Test extern classes from the Cocoa framework and extern factories
module cocoa_message_box

cocoa :: cocoa_message_box

Simple message box using the Cocoa framework
module collections

java :: collections

Basic Java collections
module combinations

combinations :: combinations

Memory-efficient Cartesian products, combinations and permutation on collections.
module common

gamnit :: common

Services common to the client and server modules
module commonmark_gen

markdown2 :: commonmark_gen

Generate Nitunit tests from commonmark specification.
module concurrent_array_and_barrier

pthreads :: concurrent_array_and_barrier

A basic usage example of the modules pthreads and pthreads::cocurrent_collections
module concurrent_collections

pthreads :: concurrent_collections

Introduces thread-safe concurrent collections
module config

config :: config

Configuration options for nit tools and apps
module console

console :: console

Defines some ANSI Terminal Control Escape Sequences.
module content_handler

sax :: content_handler

Receives notification of the logical content of a document.
module core

core :: core

Standard classes and methods used by default by Nit programs and libraries.
module counter

counter :: counter

Simple numerical statistical analysis and presentation
module cpp

cpp :: cpp

Services for compatibility with C++ code and libraries
module crapto

crapto :: crapto

Cryptographic attacks and utilities.
module crypto

crypto :: crypto

Mix of all things cryptography-related
module csv

csv :: csv

CSV document handling.
module curl

curl :: curl

Data transfer powered by the native curl library
module curl_http

curl :: curl_http

Example use of the Curl module
module curl_json

neo4j :: curl_json

cURL requests compatible with the JSON REST APIs.
module curl_rest

curl :: curl_rest

module curses

curses :: curses

Curses for Nit
module custom_serialization

serialization :: custom_serialization

Example of an ad hoc serializer that is tailored to transform business specific objects into customized representation.
module dalvik

android :: dalvik

Java related services specific to Android and its Dalvik VM
module data_store

android :: data_store

Implements app::data_store using shared_preferences
module data_store

app :: data_store

Key/value storage services
module data_store

ios :: data_store

Implements app::data_store using NSUserDefaults
module data_store

linux :: data_store

app::data_store implementation on GNU/Linux
module date

date :: date

Services to manipulate Date, Time and DateTime
module decl_handler

sax :: decl_handler

SAX2 extension handler for DTD declaration events.
module decorators

markdown :: decorators

Decorators for markdown parsing.
module depth

gamnit :: depth

Framework for 3D games in Nit
module depth_core

gamnit :: depth_core

Base entities of the depth 3D game framework
module deriving

deriving :: deriving

Automatic derivable implementations of standard basic methods.
module digraph

graph :: digraph

Implementation of directed graphs, also called digraphs.
module display

gamnit :: display

Abstract display services
module display_android

gamnit :: display_android

Gamnit display implementation for Android
module display_ios

gamnit :: display_ios

Gamnit display implementation for iOS
module display_linux

gamnit :: display_linux

Gamnit display implementation for GNU/Linux using egl, sdl and x11
module dom

dom :: dom

Easy XML DOM parser
module dot

dot :: dot

Dot rendering library
module drop_privileges

privileges :: drop_privileges

Example using the privileges module to drop privileges from root
module dtd_handler

sax :: dtd_handler

Receives notification of basic DTD-related events.
module dynamic

json :: dynamic

Dynamic interface to read values from JSON strings
module dynamic_resolution

gamnit :: dynamic_resolution

Virtual screen with a resolution independent from the real screen
module egl

egl :: egl

Interface between rendering APIs (OpenGL, OpenGL ES, etc.) and the native windowing system.
module egl

gamnit :: egl

Use of EGL to implement Gamnit on GNU/Linux and Android
module emscripten

emscripten :: emscripten

Platform for the emscripten framework
module engine_tools

serialization :: engine_tools

Advanced services for serialization engines
module english_utils

crapto :: english_utils

English language utilities for cryptographic purposes.
module entity_resolver

sax :: entity_resolver

Basic interface for resolving entities.
module error

neo4j :: error

Errors thrown by the neo4j library.
module error

json :: error

Intro JsonParseError which is exposed by all JSON reading APIs
module error_handler

sax :: error_handler

Basic interface for SAX error handlers.
module event_queue

event_queue :: event_queue

Register, update and discard events in a timeline.
module events

github :: events

Events are emitted by Github Hooks.
module events

sdl2 :: events

SDL 2 events and related services
module example_angular

popcorn :: example_angular

This is an example of how to use angular.js with popcorn
module example_vsm

vsm :: example_vsm

Example using a FileIndex
module ext

msgpack :: ext

Application specific MessagePack extension MsgPackExt
module ext

posix :: ext

Services not defined in POSIX but provided by most implementations
module ext

sax :: ext

Interfaces to optional SAX2 handlers.
module extra

pthreads :: extra

Offers some POSIX threads services that are not available on all platforms
module extra

curl :: extra

Shortcut services for scripts: http_get and http_download
module fannkuchredux

actors :: fannkuchredux

Example implemented from "The computer Language Benchmarks Game" - Fannkuch-Redux
module fca

fca :: fca

Formal Concept Analysis
module ffi_support

java :: ffi_support

Core supporting services for the FFI with Java
module file_server

nitcorn :: file_server

Provides the FileServer action, which is a standard and minimal file server
module flat

gamnit :: flat

Simple API for 2D games, built around Sprite and App::update
module flat_core

gamnit :: flat_core

Core services for the flat API for 2D games
module font

gamnit :: font

Abstract font drawing services, implemented by bmfont and tileset
module for_abuse

for_abuse :: for_abuse

Service management through the for control structure.
module foundation

cocoa :: foundation

The Foundation Kit provides basic Objective-C classes and structures
module functional

functional :: functional

Functional types and functional API for Iterator
module functional_gen

functional :: functional_gen

This module is only used to generate functional_types.nit
module functional_types

functional :: functional_types

This module provides functional type to represents various function forms.
module game

android :: game

Android services and implementation of app.nit for gamnit and mnit
module gamepad

android :: gamepad

Support for gamepad events (over Bluetooth or USB)
module gamnit

gamnit :: gamnit

Game and multimedia framework for Nit
module gamnit_android

gamnit :: gamnit_android

Support services for Gamnit on Android
module gamnit_ios

gamnit :: gamnit_ios

Support services for gamnit on iOS
module gamnit_linux

gamnit :: gamnit_linux

Support services for Gamnit on GNU/Linux
module gdk

gtk :: gdk

Services from GDK
module gdk_enums

gtk :: gdk_enums

module gen_nit

gen_nit :: gen_nit

Support to generate and otherwise manipulate Nit code
module geometry

geometry :: geometry

Provides interfaces and classes to represent basic geometry needs.
module gettext

gettext :: gettext

Internationalization of Strings using gettext library
module github

github :: github

Nit wrapper for Github API
module glesv2

glesv2 :: glesv2

OpenGL graphics rendering library for embedded systems, version 2.0
module glkit

ios :: glkit

GLKit services to create an OpenGL ES context on iOS
module gmp

gmp :: gmp

Multi precision integer and rational number using gmp lib
module graph

neo4j :: graph

Provides an interface for services on a Neo4j graphs.
module gtk

gtk :: gtk

GTK+ widgets and services
module gtk_core

gtk :: gtk_core

Classes and services to use libGTK widgets
module gtk_enums

gtk :: gtk_enums

module hash_debug

hash_debug :: hash_debug

Inject behavior analysis to hash-collections (HashMap, HashSet, etc.)
module hello

dot :: hello

Example from http://www.graphviz.org/content/hello
module hello_cocoa

cocoa :: hello_cocoa

Hello world using the Cocoa framework
module hello_ios

ios :: hello_ios

Simple iOS app with a single label
module helpers

sax :: helpers

Contains "helper" classes, including support for bootstrapping SAX-based applications.
module hooks

github :: hooks

Github hook event listening with nitcorn.
module htcpcp_server

nitcorn :: htcpcp_server

A server that implements HTCPCP. At the moment there are no additions.
module html

html :: html

HTML output facilities
module html_page

html :: html_page

module http_errors

nitcorn :: http_errors

Offers ErrorTemplate to display error pages
module http_request

app :: http_request

HTTP request services: AsyncHttpRequest and Text::http_get
module http_request

android :: http_request

Android implementation of app:http_request
module http_request

ios :: http_request

Implementation of app::http_request for iOS
module http_request

linux :: http_request

Implementation of app::http_request using GDK and Curl
module http_request

nitcorn :: http_request

Provides the HttpRequest class and services to create it
module http_request_buffer

nitcorn :: http_request_buffer

Http request parsing for buffered inputs.
module http_request_example

app :: http_request_example

Example for the app::http_request main service AsyncHttpRequest
module http_response

nitcorn :: http_response

Provides the HttpResponse class and http_status_codes
module image

sdl2 :: image

Services of the SDL_image 2.0 library
module ini

ini :: ini

Read and write INI configuration files
module input

bcm2835 :: input

module input

mnit :: input

Defines abstract classes for user and general inputs to the application.
module input_events

android :: input_events

Pointer and hardware key events
module input_ios

gamnit :: input_ios

Gamnit event support for iOS
module input_source

sax :: input_source

A single input source for an XML entity.
module inspect

serialization :: inspect

Refine Serializable::inspect to show more useful information
module intent

android :: intent

Services allowing to launch activities and start/stop services using
module intent_api10

android :: intent_api10

Services allowing to launch activities and start/stop services using
module intent_api11

android :: intent_api11

Refines intent module to add API 11 services
module intent_api12

android :: intent_api12

Refines intent module to add API 12 services
module intent_api14

android :: intent_api14

Refines intent module to add API 14 services
module intent_api15

android :: intent_api15

Refines intent module to add API 15 services
module intent_api16

android :: intent_api16

Refines intent module to add API 16 services
module intent_api17

android :: intent_api17

Refines intent module to add API 17 services
module intent_api18

android :: intent_api18

Refines intent module to add API 18 services
module intent_api19

android :: intent_api19

Refines intent module to add API 19 services
module io

java :: io

Services from the java.io package
module ios

ios :: ios

iOS platform support
module iter_extras

functional :: iter_extras

This modules provides a new functional interface for Iterator.
module java

java :: java

Supporting services for the FFI with Java and to access Java libraries
module jointask_example

pthreads :: jointask_example

Simple example of joinable task using threadpool
module json

json :: json

Read and write JSON formatted text using the standard serialization services
module json_graph_store

neo4j :: json_graph_store

Provides JSON as a mean to store graphs.
module jvm

jvm :: jvm

Java Virtual Machine invocation API and others services from the JNI C API
module keys

gamnit :: keys

Simple service keeping track of which keys are currently pressed
module landscape

gamnit :: landscape

Lock the application in the landscape orientation
module landscape

android :: landscape

Lock the application in the landscape orientation
module langannot

gettext :: langannot

Sample module showing the use of the i18n annotation
module lexer

saxophonit :: lexer

SAXophoNit’s lexer
module lexical_handler

sax :: lexical_handler

SAX2 extension handler for lexical events.
module lexpr

logic :: lexpr

Logical expression.
module libevent

libevent :: libevent

Low-level wrapper around the libevent library to manage events on file descriptors
module libevent_example

libevent :: libevent_example

Minimal usage example of libevent
module limit_fps

gamnit :: limit_fps

Frame-rate control for applications
module linux

linux :: linux

Implementation of app.nit for the Linux platform
module load_image

android :: load_image

Low-level services to load pixel data from the assets
module loader

github :: loader

module log

android :: log

Advanced Android logging services
module log

nitcorn :: log

Services inserting a timestamp in all prints and to log each requests
module logger

logger :: logger

A simple logger for Nit
module logic

logic :: logic

First-order logic data structure and algorithm.
module macro

template :: macro

String templating using macros.
module man

markdown :: man

Simple groff decorator restricted for manpages.
module mandelbrot

actors :: mandelbrot

Example implemented from "The computer Language Benchmarks Game" - Mandelbrot
module markdown

markdown :: markdown

Markdown parsing.
module markdown_ast

markdown2 :: markdown_ast

Markdown AST representation
module markdown_block_parsing

markdown2 :: markdown_block_parsing

Markdown blocks parsing
module markdown_github

markdown2 :: markdown_github

Markdown Github mode
module markdown_html_rendering

markdown2 :: markdown_html_rendering

HTML rendering of Markdown documents
module markdown_inline_parsing

markdown2 :: markdown_inline_parsing

Parser for inline markdown
module markdown_latex_rendering

markdown2 :: markdown_latex_rendering

LaTeX rendering of Markdown documents
module markdown_man_rendering

markdown2 :: markdown_man_rendering

Manpages rendering of Markdown documents
module markdown_md_rendering

markdown2 :: markdown_md_rendering

Markdown rendering of Markdown documents
module markdown_rendering

markdown2 :: markdown_rendering

Markdown document rendering
module matrix

matrix :: matrix

Services for matrices of Float values
module md5

md5 :: md5

Native MD5 digest implementation as Text::md5
module media_types

nitcorn :: media_types

Services to identify Internet media types (or MIME types, Content-types)
module meta

meta :: meta

Simple user-defined meta-level to manipulate types of instances as object.
module minimal

sdl2 :: minimal

An example to test and demonstrate the sdl2 lib with image and events
module mixer

sdl2 :: mixer

SDL2 mixer with sample/sounds and music
module model_dimensions

gamnit :: model_dimensions

Dimensions related services for Model and Mesh
module model_parser_base

gamnit :: model_parser_base

Services to parse models from a text description
module mongodb

mongodb :: mongodb

MongoDB Nit Driver.
module more_collections

more_collections :: more_collections

Highly specific, but useful, collections-related classes.
module more_lights

gamnit :: more_lights

More implementations of Light
module more_materials

gamnit :: more_materials

Various material implementations
module more_meshes

gamnit :: more_meshes

More simple geometric meshes
module more_models

gamnit :: more_models

Services to load models from the assets folder
module mpd

mpd :: mpd

Music Player Daemon client library
module mpi

mpi :: mpi

Implementation of the Message Passing Interface protocol by wrapping OpenMPI
module msgpack

msgpack :: msgpack

MessagePack, an efficient binary serialization format
module msgpack_to_json

msgpack :: msgpack_to_json

Convert MessagePack format to JSON
module mtl

gamnit :: mtl

Services to parse .mtl material files
module namespace_support

sax :: namespace_support

Encapsulates Namespace logic for use by applications using SAX, or internally by SAX drivers.
module native_app_glue

android :: native_app_glue

Wrapper of the Android native_app_glue framework to implement app.nit
module native_curl

curl :: native_curl

Binding of C libCurl which allow us to interact with network.
module native_gmp

gmp :: native_gmp

Low-level GMP features
module native_mongodb

mongodb :: native_mongodb

Native wrapper for the MongoDB C Driver
module native_notification

android :: native_notification

Native Java classes for notifications
module native_postgres

postgresql :: native_postgres

A native wrapper ove the postgres c api
module native_sqlite3

sqlite3 :: native_sqlite3

Low-level Sqlite3 features
module native_ui

android :: native_ui

Native services from the android.view and android.widget namespaces
module neo4j

neo4j :: neo4j

Neo4j connector through its JSON REST API using curl.
module network

gamnit :: network

Easy client/server logic for games and simple distributed applications
module nit_activity

android :: nit_activity

Core implementation of app.nit on Android using a custom Java entry point
module nitcc_runtime

nitcc_runtime :: nitcc_runtime

Runtime library required by parsers and lexers generated by nitcc
module nitcorn

nitcorn :: nitcorn

The nitcorn Web server framework creates server-side Web apps in Nit
module nitcorn_hello_world

nitcorn :: nitcorn_hello_world

Hello World Web server example
module nitcorn_reverse_proxy

nitcorn :: nitcorn_reverse_proxy

Minimal example using a ProxyAction
module niti_runtime

niti_runtime :: niti_runtime

Runtime library to loop around the main program for each line in file-name arguments
module nitmd

markdown :: nitmd

A Markdown parser for Nit.
module nitmd

markdown2 :: nitmd

A Markdown parser for Nit.
module nlp

nlp :: nlp

Natural Language Processor based on the StanfordNLP core.
module nlp_index

nlp :: nlp_index

Example showing how to use a NLPFileIndex.
module noise

noise :: noise

Noise generators PerlinNoise and InterpolatedNoise
module notification

android :: notification

Services to show notification in the Android status bar
module obj

gamnit :: obj

Services to parse .obj geometry files
module opengles2_hello_triangle

glesv2 :: opengles2_hello_triangle

Basic example of OpenGL ES 2.0 usage using SDL 2
module opts

opts :: opts

Management of options on the command line
module ordered_tree

ordered_tree :: ordered_tree

Manipulation and presentation of ordered trees.
module pagerank

graph :: pagerank

Add PageRank computation for vertices in Digraph.
module parser

dom :: parser

XML DOM-parsing facilities
module parser_base

parser_base :: parser_base

Simple base for hand-made parsers of all kinds
module particles

gamnit :: particles

Particle effects
module perfect_hashing

perfect_hashing :: perfect_hashing

Perfect hashing and perfect numbering
module performance_analysis

performance_analysis :: performance_analysis

Services to gather information on the performance of events by categories
module pipeline

pipeline :: pipeline

Pipelined filters and operations on iterators.
module platform

ios :: platform

Triggers compilation for the iOS platform
module platform

android :: platform

Triggers compilation for the android platform
module points_and_lines

geometry :: points_and_lines

Interfaces and classes to represent basic geometry needs.
module polygon

geometry :: polygon

Convex Polygons manipulations
module pop_auth

popcorn :: pop_auth

Authentification handlers.
module pop_config

popcorn :: pop_config

Configuration file and options for Popcorn apps
module pop_handlers

popcorn :: pop_handlers

Route handlers.
module pop_json

popcorn :: pop_json

Introduce useful services for JSON REST API handlers.
module pop_repos

popcorn :: pop_repos

Repositories for data management.
module pop_routes

popcorn :: pop_routes

Internal routes representation.
module pop_sessions

popcorn :: pop_sessions

Session handlers
module pop_tasks

popcorn :: pop_tasks

Popcorn threaded tasks
module pop_templates

popcorn :: pop_templates

Template rendering for popcorn
module pop_tests

popcorn :: pop_tests

Popcorn testing services
module pop_validation

popcorn :: pop_validation

Quick and easy validation framework for Json inputs
module popcorn

popcorn :: popcorn

Application server abstraction on top of nitcorn.
module portrait

android :: portrait

Config to set the portrait orientation
module portrait

gamnit :: portrait

Lock the application in the portrait orientation
module poset

poset :: poset

Pre order sets and partial order set (ie hierarchies)
module posix

posix :: posix

Services conforming to POSIX
module postgres

postgresql :: postgres

Services to manipulate a Postgres database
module privileges

privileges :: privileges

Process privileges management utilities
module programs

gamnit :: programs

Services for graphical programs with shaders, attributes and uniforms
module progression

progression :: progression

Event-based interface to track the progression of an operation.
module projection

matrix :: projection

Services on Matrix to transform and project 3D coordinates
module prompt

prompt :: prompt

Basic services to display a prompt
module proxy

nitcorn :: proxy

Provides the ProxyAction action, which redirects requests to another interface
module pthreads

nitcorn :: pthreads

Activate the use of pthreads with nitcorn
module pthreads

pthreads :: pthreads

Main POSIX threads support and intro the classes Thread, Mutex and Barrier
module puzzle

ai :: puzzle

The N-puzzle problem, modeled naively as a SearchProblem.
module quadtree

geometry :: quadtree

QuadTree API mostly used for 2 dimensional collision detection
module queens

ai :: queens

Example of the famous eight-queens problem solved with the ai::backtrack module.
module queries

mongodb :: queries

Mongo queries framework
module rbtree

trees :: rbtree

A red–black tree is a data structure which is a type of self-balancing binary search tree.
module reactor

nitcorn :: reactor

Core of the nitcorn project, provides HttpFactory and Action
module read

msgpack :: read

Low-level read MessagePack format from Reader streams
module reader_model

saxophonit :: reader_model

Reader’s model.
module readline

readline :: readline

GNU readline library wrapper
module realtime

realtime :: realtime

Services to keep time of the wall clock time
module redef_collections

pthreads :: redef_collections

Redef some basic collections to be thread-safe
module restful

nitcorn :: restful

Support module for the nitrestful tool and the restful annotation
module restful_annot

nitcorn :: restful_annot

Example for the restful annotation documented at lib/nitcorn/restful.nit
module ropes_debug

ropes_debug :: ropes_debug

Exposes methods for debugging ropes when needed.
module rubix

rubix :: rubix

Rubix-cube modelization library
module safe

serialization :: safe

Services for safer deserialization engines
module sax

sax :: sax

Core SAX APIs.
module sax_locator

sax :: sax_locator

Interface for associating a SAX event with a document location.
module sax_locator_impl

sax :: sax_locator_impl

Provides an optional convenience implementation of Locator.
module sax_parse_exception

sax :: sax_parse_exception

Encapsulates an XML parse error or warning.
module saxophonit

saxophonit :: saxophonit

A SAX 2 parser in Nit.
module scene2d

scene2d :: scene2d

Framework for 2D management of game elements
module sdl2

sdl2 :: sdl2

Simple DirectMedia Layer (SDL) 2.0 services for easy window creation and 2D drawing
module sdl2_base

sdl2 :: sdl2_base

Basic SDL 2 features
module search

ai :: search

Basic framework for search problems and solver.
module selection

gamnit :: selection

Select Actor from a screen coordinate
module sendmail

sendmail :: sendmail

Send emails using the sendmail program
module sensors

android :: sensors

Access Android sensors
module sequential_id

neo4j :: sequential_id

Provides a sequential identification scheme for Neo4j nodes.
module serialization

serialization :: serialization

General serialization services
module serialization_common

msgpack :: serialization_common

Serialization services for serialization_write and serialization_read
module serialization_core

serialization :: serialization_core

Abstract services to serialize Nit objects to different formats
module serialization_read

msgpack :: serialization_read

Deserialize full Nit objects from MessagePack format
module serialization_read

json :: serialization_read

Services to read JSON: deserialize_json and JsonDeserializer
module serialization_write

json :: serialization_write

Services to write Nit objects to JSON strings: serialize_to_json and JsonSerializer
module serialization_write

msgpack :: serialization_write

Serialize full Nit objects to MessagePack format
module server

gamnit :: server

Server-side network services for games and such
module server_config

nitcorn :: server_config

Classes and services to configure the server
module service

android :: service

Android service support for app.nit centered around the class Service
module sessions

nitcorn :: sessions

Automated session management
module sexp

sexp :: sexp

S-Expression parsing facilities
module sha1

sha1 :: sha1

Provides methods to compute the SHA1 hash of a String
module shadow

gamnit :: shadow

Shadow mapping using a depth texture
module shared_preferences

android :: shared_preferences

Services allowing to save and load datas to internal android device
module shared_preferences_api10

android :: shared_preferences_api10

Services to save/load data using android.content.SharedPreferences for the android platform
module shared_preferences_api11

android :: shared_preferences_api11

Refines shared_preferences module to add API 11 services
module show_basedir

xdg_basedir :: show_basedir

Prints the local base directories as per the XDG Base Directory specification
module signal_handler

nitcorn :: signal_handler

Handle SIGINT and SIGTERM to close the server after all active events
module signals

signals :: signals

ANSI C signal handling
module simple

actors :: simple

A very simple example of the actor model
module simple_file_server

nitcorn :: simple_file_server

Basic file server on port 80 by default, may require root to execute
module simple_simulation

actors :: simple_simulation

Using agent_simulation by refining the Agent class to make
module socket

socket :: socket

Socket services
module socket_c

socket :: socket_c

Low-level socket functionalities
module socket_client

socket :: socket_client

Client sample using the Socket module which connect to the server sample.
module socket_server

socket :: socket_server

Server sample using the Socket module which allow client to connect
module socket_simple_server

socket :: socket_simple_server

Simple server example using a non-blocking TCPServer
module sqlite3

sqlite3 :: sqlite3

Services to manipulate a Sqlite3 database
module standard

standard :: standard

Old module implicitly imported by the old compiler.
module stanford

nlp :: stanford

Natural Language Processor based on the StanfordNLP core.
module static

json :: static

Static interface to read Nit objects from JSON strings
module stereoscopic_view

gamnit :: stereoscopic_view

Refine EulerCamera and App::frame_core_draw to get a stereoscopic view
module store

json :: store

Store and load json data.
module symbol

symbol :: symbol

Library for simple interning of strings
module syswm

sdl2 :: syswm

Window manager related SDL 2 services
module template

template :: template

Basic template system
module test_markdown

markdown2 :: test_markdown

Test suites for module markdown
module testing

saxophonit :: testing

Various utilities to help testing SAXophoNit (and SAX parsers in general).
module text_stat

text_stat :: text_stat

Injects stat-calculating functionalities to Text and its variants
module texture_atlas_parser

gamnit :: texture_atlas_parser

Tool to parse XML texture atlas and generated Nit code to access subtextures
module textures

gamnit :: textures

Load textures, create subtextures and manage their life-cycle
module thread_ring

actors :: thread_ring

Example implemented from "The computer Language Benchmarks Game" - Thread-Ring
module threaded_example

pthreads :: threaded_example

test for threaded annotation
module threadpool

pthreads :: threadpool

Introduces a minimal ThreadPool implementation using Tasks
module threadpool_example

pthreads :: threadpool_example

Simple example using threadpool
module tileset

gamnit :: tileset

Support for TileSet, TileSetFont and drawing text with TextSprites
module toast

android :: toast

Services to display a toast, a small popup on Android
module token

nitcorn :: token

Simple generate_token service, independent of the rest of the nitcorn framework
module trees

trees :: trees

General module for tree data structures
module trie

trees :: trie

A trie (or prefix tree) is a datastructure used to perform prefix searches.
module u16_string

core :: u16_string

Wrapper of ICU's UTF-16 encoded strings and conversion
module ui

ios :: ui

Implementation of app::ui for iOS
module ui

linux :: ui

Implementation of the app.nit UI module for GNU/Linux
module ui

app :: ui

Portable UI controls for mobiles apps
module ui

android :: ui

Views and services to use the Android native user interface
module ui_example

app :: ui_example

User interface example using app::ui
module ui_test

android :: ui_test

Test for app.nit's UI services
module uikit

ios :: uikit

File generated by objcwrapper
module undirected_clusters

dot :: undirected_clusters

Example from http://www.graphviz.org/Gallery/undirected/fdpclust.html
module v3_10

gtk :: v3_10

GTK+ services added at version 3.10
module v3_4

gtk :: v3_4

module v3_6

gtk :: v3_6

GTK+ services added at version 3.6
module v3_8

gtk :: v3_8

GTK+ services added at version 3.8
module vararg_routes

nitcorn :: vararg_routes

Routes with parameters.
module vibration

android :: vibration

Vibration services for Android
module virtual_gamepad

gamnit :: virtual_gamepad

Virtual gamepad mapped to keyboard keys for quick and dirty mobile support
module vr

gamnit :: vr

VR support for gamnit depth, for Android only
module vsm

vsm :: vsm

Vector Space Model
module wallet

github :: wallet

Github OAuth tokens management
module websocket

websocket :: websocket

Adds support for a websocket connection in Nit
module websocket_server

websocket :: websocket_server

Sample module for a minimal chat server using Websockets on port 8088
module wifi

android :: wifi

Simple wrapper of the Android WiFi services
module write

msgpack :: write

Low-level write in MessagePack format to Writer streams
module x11

x11 :: x11

Services from the X11 library
module xdg_basedir

xdg_basedir :: xdg_basedir

Services for using the XDG Base Directory specification
module xml_entities

dom :: xml_entities

Basic blocks for DOM-XML representation
module xml_filter

sax :: xml_filter

Interface for an XML filter.
module xml_filter_impl

sax :: xml_filter_impl

Base class for deriving an XML filter.
module xml_reader

sax :: xml_reader

Interface for reading an XML document using callbacks.
module xor

crapto :: xor

Cryptographic attacks and utilities for XOR-based algorithms.
module xor_ciphers

crypto :: xor_ciphers

XOR oriented cryptographic ciphers and utilities.
# File manipulations (create, read, write, etc.)
module file

intrude import stream
intrude import text::ropes
import text
import time
import gc

in "C Header" `{
	#include <dirent.h>
	#include <string.h>
	#include <sys/types.h>
	#include <sys/stat.h>
	#include <unistd.h>
	#include <stdio.h>
	#include <errno.h>
#ifndef _WIN32
	#include <poll.h>
#endif
`}

in "C" `{
#ifdef _WIN32
	#include <windows.h>
#endif
`}

# `Stream` used to interact with a File or FileDescriptor
abstract class FileStream
	super Stream
	# The path of the file.
	var path: nullable String = null

	# The FILE *.
	private var file: nullable NativeFile = null

	# The status of a file. see POSIX stat(2).
	#
	#     var f = new FileReader.open("/etc/issue")
	#     assert f.file_stat.is_file
	#
	# Return null in case of error
	fun file_stat: nullable FileStat
	do
		var stat = _file.as(not null).file_stat
		if stat.address_is_null then return null
		return new FileStat(stat)
	end

	# File descriptor of this file
	fun fd: Int do return _file.as(not null).fileno

	redef fun close
	do
		var file = _file
		if file == null then return
		if file.address_is_null then
			if last_error != null then return
			last_error = new IOError("Cannot close unopened file")
			return
		end
		var i = file.io_close
		if i != 0 then
			last_error = new IOError("Close failed due to error {sys.errno.strerror}")
		end
		_file = null
	end

	# Sets the buffering mode for the current FileStream
	#
	# If the buf_size is <= 0, its value will be 512 by default
	#
	# The mode is any of the buffer_mode enumeration in `Sys`:
	#
	# * `buffer_mode_full`
	# * `buffer_mode_line`
	# * `buffer_mode_none`
	fun set_buffering_mode(buf_size, mode: Int) do
		if buf_size <= 0 then buf_size = 512
		if _file.as(not null).set_buffering_type(buf_size, mode) != 0 then
			last_error = new IOError("Error while changing buffering type for FileStream, returned error {sys.errno.strerror}")
		end
	end
end

# `Stream` that can read from a File
class FileReader
	super FileStream
	super PollableReader
	# Misc

	# Open the same file again.
	# The original path is reused, therefore the reopened file can be a different file.
	#
	#     var f = new FileReader.open("/etc/issue")
	#     var l = f.read_line
	#     f.reopen
	#     assert l == f.read_line
	fun reopen
	do
		var fl = _file
		if fl != null and not fl.address_is_null then close
		last_error = null
		_file = new NativeFile.io_open_read(path.as(not null).to_cstring)
		if _file.as(not null).address_is_null then
			last_error = new IOError("Cannot open `{path.as(not null)}`: {sys.errno.strerror}")
			return
		end
	end

	redef fun raw_read_byte
	do
		var nb = _file.as(not null).io_read(write_buffer, 1)
		if last_error == null and _file.as(not null).ferror then
			last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
		end
		if nb == 0 then return -1
		return write_buffer[0].to_i
	end

	redef fun raw_read_bytes(cstr, max)
	do
		var nb = _file.as(not null).io_read(cstr, max)
		if last_error == null and _file.as(not null).ferror then
			last_error = new IOError("Cannot read `{path.as(not null)}`: {sys.errno.strerror}")
		end
		return nb
	end

	redef fun eof do
		var fl = _file
		if fl == null then return true
		if fl.address_is_null then return true
		if last_error != null then return true
		if super then
			if last_error != null then return true
			return fl.feof
		end
		return false
	end

	# Open the file at `path` for reading.
	#
	#     var f = new FileReader.open("/etc/issue")
	#     assert not f.eof
	#     f.close
	#
	# In case of error, `last_error` is set
	#
	#     f = new FileReader.open("/fail/does not/exist")
	#     assert f.eof
	#     assert f.last_error != null
	init open(path: String)
	do
		self.path = path
		_file = new NativeFile.io_open_read(path.to_cstring)
		if _file.as(not null).address_is_null then
			last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
		end
	end

	# Creates a new File stream from a file descriptor
	#
	# This is a low-level method.
	init from_fd(fd: Int) do
		self.path = ""
		_file = fd.fd_to_stream(read_only)
		if _file.as(not null).address_is_null then
			last_error = new IOError("Error: Converting fd {fd} to stream failed with '{sys.errno.strerror}'")
		end
	end

	redef fun poll_in
	do
		var res = native_poll_in(fd)
		if res == -1 then
			last_error = new IOError(errno.to_s)
			return false
		else return res > 0
	end

	private fun native_poll_in(fd: Int): Int `{
#ifndef _WIN32
		struct pollfd fds = {(int)fd, POLLIN, 0};
		return poll(&fds, 1, 0);
#else
		return 0;
#endif
	`}
end

# `Stream` that can write to a File
class FileWriter
	super FileStream
	super Writer

	redef fun write_bytes_from_cstring(cs, len) do
		if last_error != null then return
		if not _is_writable then
			last_error = new IOError("cannot write to non-writable stream")
			return
		end
		write_native(cs, 0, len)
	end

	redef fun write(s)
	do
		if last_error != null then return
		if not _is_writable then
			last_error = new IOError("cannot write to non-writable stream")
			return
		end
		s.write_native_to(self)
	end

	redef fun write_byte(value)
	do
		if last_error != null then return
		if not _is_writable then
			last_error = new IOError("Cannot write to non-writable stream")
			return
		end
		if _file.as(not null).address_is_null then
			last_error = new IOError("Writing on a null stream")
			_is_writable = false
			return
		end

		var err = _file.as(not null).write_byte(value)
		if err != 1 then
			# Big problem
			last_error = new IOError("Problem writing a byte: {err}")
		end
	end

	redef fun close
	do
		super
		_is_writable = false
	end
	redef var is_writable = false

	# Write `len` bytes from `native`.
	private fun write_native(native: CString, from, len: Int)
	do
		if last_error != null then return
		if not _is_writable then
			last_error = new IOError("Cannot write to non-writable stream")
			return
		end
		if _file.as(not null).address_is_null then
			last_error = new IOError("Writing on a null stream")
			_is_writable = false
			return
		end
		var err = _file.as(not null).io_write(native, from, len)
		if err != len then
			# Big problem
			last_error = new IOError("Problem in writing : {err} {len} \n")
		end
	end

	# Open the file at `path` for writing.
	init open(path: String)
	do
		_file = new NativeFile.io_open_write(path.to_cstring)
		self.path = path
		_is_writable = true
		if _file.as(not null).address_is_null then
			last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
			is_writable = false
		end
	end

	# Creates a new File stream from a file descriptor
	init from_fd(fd: Int) do
		self.path = ""
		_file = fd.fd_to_stream(wipe_write)
		_is_writable = true
		 if _file.as(not null).address_is_null then
			 last_error = new IOError("Error: Opening stream from file descriptor {fd} failed with '{sys.errno.strerror}'")
			_is_writable = false
		end
	end
end

redef class Int
	# Creates a file stream from a file descriptor `fd` using the file access `mode`.
	#
	# NOTE: The `mode` specified must be compatible with the one used in the file descriptor.
	private fun fd_to_stream(mode: CString): NativeFile `{
		return fdopen((int)self, mode);
	`}

	# Does the file descriptor `self` refer to a terminal?
	fun isatty: Bool `{ return isatty(self); `}
end

# Constant for read-only file streams
private fun read_only: CString do return once "r".to_cstring

# Constant for write-only file streams
#
# If a stream is opened on a file with this method,
# it will wipe the previous file if any.
# Else, it will create the file.
private fun wipe_write: CString do return once "w".to_cstring

###############################################################################

# Standard input stream.
#
# The class of the default value of `sys.stdin`.
class Stdin
	super FileReader

	init do
		_file = new NativeFile.native_stdin
		path = "/dev/stdin"
	end
end

# Standard output stream.
#
# The class of the default value of `sys.stdout`.
class Stdout
	super FileWriter
	init do
		_file = new NativeFile.native_stdout
		path = "/dev/stdout"
		_is_writable = true
		set_buffering_mode(256, sys.buffer_mode_line)
	end
end

# Standard error stream.
#
# The class of the default value of `sys.stderr`.
class Stderr
	super FileWriter
	init do
		_file = new NativeFile.native_stderr
		path = "/dev/stderr"
		_is_writable = true
	end
end

###############################################################################

redef class Writable
	# Like `write_to` but take care of creating the file
	fun write_to_file(filepath: String)
	do
		var stream = new FileWriter.open(filepath)
		write_to(stream)
		stream.close
	end
end

# Utility class to access file system services.
#
# Usually created with `Text::to_path`.
#
# `Path` objects does not necessarily represent existing files in a file system.
# They are sate-less objects that efficiently represent path information.
# They also provide an easy to use API on file-system services and are used to store their error status (see `last_error`)
class Path

	private var path: String

	# Path to this file
	redef fun to_s do return path

	# Short name of the file at `to_s`
	#
	# ~~~
	# var path = "/tmp/somefile".to_path
	# assert path.filename == "somefile"
	# ~~~
	#
	# The result does not depend of the file system, thus is cached for efficiency.
	var filename: String = path.basename is lazy

	# The path simplified by removing useless `.`, removing `//`, and resolving `..`
	#
	# ~~~
	# var path = "somedir/./tmp/../somefile".to_path
	# assert path.simplified.to_s == "somedir/somefile"
	# ~~~
	#
	# See `String:simplify_path` for details.
	#
	# The result does not depend of the file system, thus is cached for efficiency.
	var simplified: Path is lazy do
		var res = path.simplify_path.to_path
		res.simplified = res
		return res
	end

	# Return the directory part of the path.
	#
	# ~~~
	# var path = "/foo/bar/baz".to_path
	# assert path.dir.to_s == "/foo/bar"
	# assert path.dir.dir.to_s == "/foo"
	# assert path.dir.dir.dir.to_s == "/"
	# ~~~
	#
	# See `String:dirname` for details.
	#
	# The result does not depend of the file system, thus is cached for efficiency.
	var dir: Path is lazy do
		return path.dirname.to_path
	end

	# Last error produced by I/O operations.
	#
	# ~~~
	# var path = "/does/not/exists".to_path
	# assert path.last_error == null
	# path.read_all
	# assert path.last_error != null
	# ~~~
	#
	# Since `Path` objects are stateless, `last_error` is reset on most operations and reflect its status.
	var last_error: nullable IOError = null is writable

	# Does the file at `path` exists?
	#
	# If the file does not exists, `last_error` is set to the information.
	fun exists: Bool do return stat != null

	# Information on the file at `self` following symbolic links
	#
	# Returns `null` if there is no file at `self`.
	# `last_error` is updated to contains the error information on error, and null on success.
	#
	#     assert "/etc/".to_path.stat.is_dir
	#     assert "/etc/issue".to_path.stat.is_file
	#     assert "/fail/does not/exist".to_path.stat == null
	#
	# ~~~
	# var p = "/tmp/".to_path
	# var stat = p.stat
	# if stat != null then # Does `p` exist?
	#     print "It's size is {stat.size}"
	#     if stat.is_dir then print "It's a directory"
	# else
	#     print p.last_error.to_s
	# end
	# ~~~
	fun stat: nullable FileStat
	do
		var stat = path.to_cstring.file_stat
		if stat.address_is_null then
			last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
			return null
		end
		last_error = null
		return new FileStat(stat)
	end

	# Information on the file or link at `self`
	#
	# Do not follow symbolic links.
	fun link_stat: nullable FileStat
	do
		var stat = path.to_cstring.file_lstat
		if stat.address_is_null then
			last_error = new IOError("Cannot open `{path}`: {sys.errno.strerror}")
			return null
		end
		last_error = null
		return new FileStat(stat)
	end

	# Delete a file from the file system.
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	fun delete
	do
		var res = path.to_cstring.file_delete
		if not res then
			last_error = new IOError("Cannot delete `{path}`: {sys.errno.strerror}")
		else
			last_error = null
		end
	end

	# Copy content of file at `path` to `dest`.
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	fun copy(dest: Path)
	do
		last_error = null
		var input = open_ro
		var output = dest.open_wo

		var buffer = new CString(4096)
		while not input.eof do
			var read = input.read_bytes_to_cstring(buffer, 4096)
			output.write_bytes_from_cstring(buffer, read)
		end

		input.close
		output.close
		last_error = input.last_error or else output.last_error
	end

	# Open this file for reading.
	#
	# ~~~
	# var file = "/etc/issue".to_path.open_ro
	# print file.read_line
	# file.close
	# ~~~
	#
	# Note that it is the user's responsibility to close the stream.
	# Therefore, for simple use case, look at `read_all` or `each_line`.
	#
	# ENSURE `last_error == result.last_error`
	fun open_ro: FileReader
	do
		var res = new FileReader.open(path)
		last_error = res.last_error
		return res
	end

	# Open this file for writing
	#
	# ~~~
	# var file = "bla.log".to_path.open_wo
	# file.write "Blabla\n"
	# file.close
	# ~~~
	#
	# Note that it is the user's responsibility to close the stream.
	# Therefore, for simple use case, look at `Writable::write_to_file`.
	#
	# ENSURE `last_error == result.last_error`
	fun open_wo: FileWriter
	do
		var res = new FileWriter.open(path)
		last_error = res.last_error
		return res
	end

	# Read all the content of the file as a string.
	#
	# ~~~
	# var content = "/etc/issue".to_path.read_all
	# print content
	# ~~~
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	# In case of error, the result might be empty or truncated.
	#
	# See `Reader::read_all` for details.
	fun read_all: String do return read_all_bytes.to_s

	# Read all the content on the file as a raw sequence of bytes.
	#
	# ~~~
	# var content = "/etc/issue".to_path.read_all_bytes
	# print content.to_s
	# ~~~
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	# In case of error, the result might be empty or truncated.
	fun read_all_bytes: Bytes
	do
		var s = open_ro
		var res = s.read_all_bytes
		s.close
		last_error = s.last_error
		return res
	end

	# Read all the lines of the file
	#
	# ~~~
	# var lines = "/etc/passwd".to_path.read_lines
	#
	# print "{lines.length} users"
	#
	# for l in lines do
	#     var fields = l.split(":")
	#     print "name={fields[0]} uid={fields[2]}"
	# end
	# ~~~
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	# In case of error, the result might be empty or truncated.
	#
	# See `Reader::read_lines` for details.
	fun read_lines: Array[String]
	do
		var s = open_ro
		var res = s.read_lines
		s.close
		last_error = s.last_error
		return res
	end

	# Return an iterator on each line of the file
	#
	# ~~~
	# for l in "/etc/passwd".to_path.each_line do
	#     var fields = l.split(":")
	#     print "name={fields[0]} uid={fields[2]}"
	# end
	# ~~~
	#
	# Note: the stream is automatically closed at the end of the file (see `LineIterator::close_on_finish`)
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	#
	# See `Reader::each_line` for details.
	fun each_line: LineIterator
	do
		var s = open_ro
		var res = s.each_line
		res.close_on_finish = true
		last_error = s.last_error
		return res
	end

	# Correctly join `self` with `subpath` using the directory separator.
	#
	# Using a standard "{self}/{path}" does not work in the following cases:
	#
	# * `self` is empty.
	# * `path` starts with `'/'`.
	#
	# This method ensures that the join is valid.
	#
	#     var hello = "hello".to_path
	#     assert (hello/"world").to_s   == "hello/world"
	#     assert ("hel/lo".to_path / "wor/ld").to_s == "hel/lo/wor/ld"
	#     assert ("".to_path / "world").to_s == "world"
	#     assert (hello / "/world").to_s  == "/world"
	#     assert ("hello/".to_path / "world").to_s  == "hello/world"
	fun /(subpath: String): Path do return new Path(path / subpath)

	# Lists the files contained within the directory at `path`.
	#
	#     var files = "/etc".to_path.files
	#     assert files.has("/etc/issue".to_path)
	#
	# `last_error` is updated to contains the error information on error, and null on success.
	# In case of error, the result might be empty or truncated.
	#
	#     var path = "/etc/issue".to_path
	#     files = path.files
	#     assert files.is_empty
	#     assert path.last_error != null
	fun files: Array[Path]
	do
		last_error = null
		var res = new Array[Path]
		var d = new NativeDir.opendir(path.to_cstring)
		if d.address_is_null then
			last_error = new IOError("Cannot list directory `{path}`: {sys.errno.strerror}")
			return res
		end

		loop
			var de = d.readdir
			if de.address_is_null then
				# readdir cannot fail, so null means end of list
				break
			end
			var name = de.to_s
			if name == "." or name == ".." then continue
			res.add self / name
		end
		d.closedir

		return res
	end

	# Is `self` the path to an existing directory ?
	#
	# ~~~nit
	# assert ".".to_path.is_dir
	# assert not "/etc/issue".to_path.is_dir
	# assert not "/should/not/exist".to_path.is_dir
	# ~~~
	fun is_dir: Bool do
		var st = stat
		if st == null then return false
		return st.is_dir
	end

	# Recursively delete a directory and all of its content
	#
	# Does not go through symbolic links and may get stuck in a cycle if there
	# is a cycle in the file system.
	#
	# `last_error` is updated with the first encountered error, or null on success.
	# The method does not stop on the first error and tries to remove the most files and directories.
	#
	# ~~~
	# var path = "/does/not/exists/".to_path
	# path.rmdir
	# assert path.last_error != null
	#
	# path = "/tmp/path/to/create".to_path
	# path.to_s.mkdir
	# assert path.exists
	# path.rmdir
	# assert path.last_error == null
	# ~~~
	fun rmdir
	do
		var first_error = null
		for file in self.files do
			var stat = file.link_stat
			if stat == null then
				if first_error == null then first_error = file.last_error
				continue
			end
			if stat.is_dir then
				# Recursively rmdir
				file.rmdir
			else
				file.delete
			end
			if first_error == null then first_error = file.last_error
		end

		# Delete the directory itself if things are fine
		if first_error == null then
			if not path.to_cstring.rmdir then
				first_error = new IOError("Cannot remove `{self}`: {sys.errno.strerror}")
			end
		end
		self.last_error = first_error
	end

	redef fun ==(other) do return other isa Path and simplified.path == other.simplified.path
	redef fun hash do return simplified.path.hash
end

# Information on a file
#
# Created by `Path::stat` and `Path::link_stat`.
#
# The information within this class is gathered when the instance is initialized
# it will not be updated if the targeted file is modified.
class FileStat
	super Finalizable

	# TODO private init

	# The low-level status of a file
	#
	# See: POSIX stat(2)
	private var stat: NativeFileStat

	private var finalized = false

	redef fun finalize
	do
		if not finalized then
			stat.free
			finalized = true
		end
	end

	# Returns the last access time in seconds since Epoch
	fun last_access_time: Int
	do
		assert not finalized
		return stat.atime
	end

	# Returns the last access time
	#
	# alias for `last_access_time`
	fun atime: Int do return last_access_time

	# Returns the last modification time in seconds since Epoch
	fun last_modification_time: Int
	do
		assert not finalized
		return stat.mtime
	end

	# Returns the last modification time
	#
	# alias for `last_modification_time`
	fun mtime: Int do return last_modification_time


	# Size of the file at `path`
	fun size: Int
	do
		assert not finalized
		return stat.size
	end

	# Is self a regular file and not a device file, pipe, socket, etc.?
	fun is_file: Bool
	do
		assert not finalized
		return stat.is_reg
	end

	# Alias for `is_file`
	fun is_reg: Bool do return is_file

	# Is this a directory?
	fun is_dir: Bool
	do
		assert not finalized
		return stat.is_dir
	end

	# Is this a symbolic link?
	fun is_link: Bool
	do
		assert not finalized
		return stat.is_lnk
	end

	# FIXME Make the following POSIX only? or implement in some other way on Windows

	# Returns the last status change time in seconds since Epoch
	fun last_status_change_time: Int
	do
		assert not finalized
		return stat.ctime
	end

	# Returns the last status change time
	#
	# alias for `last_status_change_time`
	fun ctime: Int do return last_status_change_time

	# Returns the permission bits of file
	fun mode: Int
	do
		assert not finalized
		return stat.mode
	end

	# Is this a character device?
	fun is_chr: Bool
	do
		assert not finalized
		return stat.is_chr
	end

	# Is this a block device?
	fun is_blk: Bool
	do
		assert not finalized
		return stat.is_blk
	end

	# Is this a FIFO pipe?
	fun is_fifo: Bool
	do
		assert not finalized
		return stat.is_fifo
	end

	# Is this a UNIX socket
	fun is_sock: Bool
	do
		assert not finalized
		return stat.is_sock
	end
end

redef class Text
	# Access file system related services on the path at `self`
	fun to_path: Path do return new Path(to_s)

	private fun write_native_to(s: FileWriter)
	do
		for i in substrings do s.write_native(i.to_cstring, 0, i.byte_length)
	end

	# return true if a file with this names exists
	fun file_exists: Bool do return to_cstring.file_exists

	# The status of a file. see POSIX stat(2).
	fun file_stat: nullable FileStat
	do
		var stat = to_cstring.file_stat
		if stat.address_is_null then return null
		return new FileStat(stat)
	end

	# The status of a file or of a symlink. see POSIX lstat(2).
	fun file_lstat: nullable FileStat
	do
		var stat = to_cstring.file_lstat
		if stat.address_is_null then return null
		return new FileStat(stat)
	end

	# Remove a file, return true if success
	fun file_delete: Bool do return to_cstring.file_delete

	# Copy content of file at `self` to `dest`
	fun file_copy_to(dest: String) do to_path.copy(dest.to_path)

	# Remove the trailing `extension`.
	#
	# `extension` usually starts with a dot but could be anything.
	#
	#     assert "file.txt".strip_extension(".txt")   == "file"
	#     assert "file.txt".strip_extension("le.txt") == "fi"
	#     assert "file.txt".strip_extension("xt")     == "file.t"
	#
	# If `extension == null`, the rightmost extension is stripped, including the last dot.
	#
	#     assert "file.txt".strip_extension           == "file"
	#
	# If `extension` is not present, `self` is returned unmodified.
	#
	#     assert "file.txt".strip_extension(".tar.gz")  == "file.txt"
	fun strip_extension(extension: nullable String): String
	do
		if extension == null then
			extension = file_extension
			if extension == null then
				return self.to_s
			else extension = ".{extension}"
		end

		if has_suffix(extension) then
			return substring(0, length - extension.length).to_s
		end
		return self.to_s
	end

	# Extract the basename of a path and strip the `extension`
	#
	# The extension is stripped only if `extension != null`.
	#
	#     assert "/path/to/a_file.ext".basename(".ext")     == "a_file"
	#     assert "path/to/a_file.ext".basename(".ext")      == "a_file"
	#     assert "path/to/a_file.ext".basename              == "a_file.ext"
	#     assert "path/to".basename(".ext")                 == "to"
	#     assert "path/to/".basename(".ext")                == "to"
	#     assert "path/to".basename                         == "to"
	#     assert "path".basename                            == "path"
	#     assert "/path".basename                           == "path"
	#     assert "/".basename                               == "/"
	#     assert "".basename                                == ""
	#
	# On Windows, '\' are replaced by '/':
	#
	# ~~~nitish
	# assert "C:\\path\\to\\a_file.ext".basename(".ext")    == "a_file"
	# assert "C:\\".basename                                == "C:"
	# ~~~
	fun basename(extension: nullable String): String
	do
		var n = self
		if is_windows then n = n.replace("\\", "/")

		var l = length - 1 # Index of the last char
		while l > 0 and self.chars[l] == '/' do l -= 1 # remove all trailing `/`
		if l == 0 then return "/"
		var pos = chars.last_index_of_from('/', l)
		if pos >= 0 then
			n = substring(pos+1, l-pos)
		end

		if extension != null then
			return n.strip_extension(extension)
		else return n.to_s
	end

	# Extract the dirname of a path
	#
	#     assert "/path/to/a_file.ext".dirname         == "/path/to"
	#     assert "path/to/a_file.ext".dirname          == "path/to"
	#     assert "path/to".dirname                     == "path"
	#     assert "path/to/".dirname                    == "path"
	#     assert "path".dirname                        == "."
	#     assert "/path".dirname                       == "/"
	#     assert "/".dirname                           == "/"
	#     assert "".dirname                            == "."
	#
	# On Windows, '\' are replaced by '/':
	#
	# ~~~nitish
	# assert "C:\\path\\to\\a_file.ext".dirname        == "C:/path/to"
	# assert "C:\\file".dirname                        == "C:"
	# ~~~
	fun dirname: String
	do
		var s = self
		if is_windows then s = s.replace("\\", "/")

		var l = length - 1 # Index of the last char
		while l > 0 and s.chars[l] == '/' do l -= 1 # remove all trailing `/`
		var pos = s.chars.last_index_of_from('/', l)
		if pos > 0 then
			return s.substring(0, pos).to_s
		else if pos == 0 then
			return "/"
		else
			return "."
		end
	end

	# Return the canonicalized absolute pathname (see POSIX function `realpath`)
	#
	# Require: `file_exists`
	fun realpath: String do
		var cs = to_cstring.file_realpath
		assert file_exists
		var res = cs.to_s
		cs.free
		return res
	end

	# Simplify a file path by remove useless `.`, removing `//`, and resolving `..`
	#
	# * `..` are not resolved if they start the path
	# * starting `.` is simplified unless the path is empty
	# * starting `/` is not removed
	# * trailing `/` is removed
	#
	# Note that the method only work on the string:
	#
	#  * no I/O access is performed
	#  * the validity of the path is not checked
	#
	# ~~~
	# assert "some/./complex/../../path/from/../to/a////file//".simplify_path	     ==  "path/to/a/file"
	# assert "../dir/file".simplify_path       ==  "../dir/file"
	# assert "dir/../../".simplify_path        ==  ".."
	# assert "dir/..".simplify_path            ==  "."
	# assert "//absolute//path/".simplify_path ==  "/absolute/path"
	# assert "//absolute//../".simplify_path   ==  "/"
	# assert "/".simplify_path                 == "/"
	# assert "../".simplify_path               == ".."
	# assert "./".simplify_path                == "."
	# assert "././././././".simplify_path      == "."
	# assert "./../dir".simplify_path		   == "../dir"
	# assert "./dir".simplify_path			   == "dir"
	# ~~~
	#
	# On Windows, '\' are replaced by '/':
	#
	# ~~~nitish
	# assert "C:\\some\\.\\complex\\../../path/to/a_file.ext".simplify_path == "C:/path/to/a_file.ext"
	# assert "C:\\".simplify_path              == "C:"
	# ~~~
	fun simplify_path: String
	do
		var s = self
		if is_windows then s = s.replace("\\", "/")
		var a = s.split_with("/")
		var a2 = new Array[String]
		for x in a do
			if x == "." and not a2.is_empty then continue # skip `././`
			if x == "" and not a2.is_empty then continue # skip `//`
			if x == ".." and not a2.is_empty and a2.last != ".." then
				if a2.last == "." then # do not skip `./../`
					a2.pop # reduce `./../` in `../`
				else # reduce `dir/../` in `/`
					a2.pop
					continue
				end
			else if not a2.is_empty and a2.last == "." then
				a2.pop # reduce `./dir` in `dir`
			end
			a2.push(x)
		end
		if a2.is_empty then return "."
		if a2.length == 1 and a2.first == "" then return "/"
		return a2.join("/")
	end

	# Correctly join two path using the directory separator.
	#
	# Using a standard "{self}/{path}" does not work in the following cases:
	#
	# * `self` is empty.
	# * `path` starts with `'/'`.
	#
	# This method ensures that the join is valid.
	#
	#     assert "hello".join_path("world")   == "hello/world"
	#     assert "hel/lo".join_path("wor/ld") == "hel/lo/wor/ld"
	#     assert "".join_path("world")        == "world"
	#     assert "hello".join_path("/world")  == "/world"
	#     assert "hello/".join_path("world")  == "hello/world"
	#     assert "hello/".join_path("/world") == "/world"
	#
	# Note: You may want to use `simplify_path` on the result.
	#
	# Note: This method works only with POSIX paths.
	fun join_path(path: Text): String
	do
		if path.is_empty then return self.to_s
		if self.is_empty then return path.to_s
		if path.chars[0] == '/' then return path.to_s
		if self.last == '/' then return "{self}{path}"
		return "{self}/{path}"
	end

	# Convert the path (`self`) to a program name.
	#
	# Ensure the path (`self`) will be treated as-is by POSIX shells when it is
	# used as a program name. In order to do that, prepend `./` if needed.
	#
	#     assert "foo".to_program_name == "./foo"
	#     assert "/foo".to_program_name == "/foo"
	#     assert "".to_program_name == "./" # At least, your shell will detect the error.
	fun to_program_name: String do
		if self.has_prefix("/") then
			return self.to_s
		else
			return "./{self}"
		end
	end

	# Alias for `join_path`
	#
	#     assert "hello" / "world"      ==  "hello/world"
	#     assert "hel/lo" / "wor/ld"    ==  "hel/lo/wor/ld"
	#     assert "" / "world"           ==  "world"
	#     assert "/hello" / "/world"    ==  "/world"
	#
	# This operator is quite useful for chaining changes of path.
	# The next one being relative to the previous one.
	#
	#     var a = "foo"
	#     var b = "/bar"
	#     var c = "baz/foobar"
	#     assert a/b/c == "/bar/baz/foobar"
	fun /(path: Text): String do return join_path(path)

	# Returns the relative path needed to go from `self` to `dest`.
	#
	#     assert "/foo/bar".relpath("/foo/baz") == "../baz"
	#     assert "/foo/bar".relpath("/baz/bar") == "../../baz/bar"
	#
	# If `self` or `dest` is relative, they are considered relatively to `getcwd`.
	#
	# In some cases, the result is still independent of the current directory:
	#
	#     assert "foo/bar".relpath("..") == "../../.."
	#
	# In other cases, parts of the current directory may be exhibited:
	#
	#     var p = "../foo/bar".relpath("baz")
	#     var c = getcwd.basename
	#     assert p == "../../{c}/baz"
	#
	# For path resolution independent of the current directory (eg. for paths in URL),
	# or to use an other starting directory than the current directory,
	# just force absolute paths:
	#
	#     var start = "/a/b/c/d"
	#     var p2 = (start/"../foo/bar").relpath(start/"baz")
	#     assert p2 == "../../d/baz"
	#
	#
	# Neither `self` or `dest` has to be real paths or to exist in directories since
	# the resolution is only done with string manipulations and without any access to
	# the underlying file system.
	#
	# If `self` and `dest` are the same directory, the empty string is returned:
	#
	#     assert "foo".relpath("foo") == ""
	#     assert "foo/../bar".relpath("bar") == ""
	#
	# The empty string and "." designate both the current directory:
	#
	#     assert "".relpath("foo/bar")  == "foo/bar"
	#     assert ".".relpath("foo/bar") == "foo/bar"
	#     assert "foo/bar".relpath("")  == "../.."
	#     assert "/" + "/".relpath(".") == getcwd
	fun relpath(dest: String): String
	do
		# TODO windows support
		var cwd = getcwd
		var from = (cwd/self).simplify_path.split("/")
		if from.last.is_empty then from.pop # case for the root directory
		var to = (cwd/dest).simplify_path.split("/")
		if to.last.is_empty then to.pop # case for the root directory

		# Remove common prefixes
		while not from.is_empty and not to.is_empty and from.first == to.first do
			from.shift
			to.shift
		end

		# Result is going up in `from` with ".." then going down following `to`
		var from_len = from.length
		if from_len == 0 then return to.join("/")
		var up = "../"*(from_len-1) + ".."
		if to.is_empty then return up
		var res = up + "/" + to.join("/")
		return res
	end

	# Create a directory (and all intermediate directories if needed)
	#
	# The optional `mode` parameter specifies the permissions of the directory,
	# the default value is `0o777`.
	#
	# Return an error object in case of error.
	#
	#    assert "/etc/".mkdir != null
	fun mkdir(mode: nullable Int): nullable Error
	do
		mode = mode or else 0o777
		var s = self
		if is_windows then s = s.replace("\\", "/")

		var dirs = s.split_with("/")
		var path = new FlatBuffer
		if dirs.is_empty then return null
		if dirs[0].is_empty then
			# it was a starting /
			path.add('/')
		end
		var error: nullable Error = null
		for i in [0 .. dirs.length - 1[ do
			var d = dirs[i]
			if d.is_empty then continue
			path.append(d)
			path.add('/')
			if path.file_exists then continue
			var res = path.to_cstring.file_mkdir(mode)
			if not res and error == null then
				error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
			end
		end
		var res = s.to_cstring.file_mkdir(mode)
		if not res and error == null then
			error = new IOError("Cannot create directory `{path}`: {sys.errno.strerror}")
		end
		return error
	end

	# Delete a directory and all of its content, return `true` on success
	#
	# Does not go through symbolic links and may get stuck in a cycle if there
	# is a cycle in the filesystem.
	#
	# Return an error object in case of error.
	#
	#     assert "/fail/does not/exist".rmdir != null
	fun rmdir: nullable Error
	do
		var p = to_path
		p.rmdir
		return p.last_error
	end

	# Change the current working directory
	#
	#     "/etc".chdir
	#     assert getcwd == "/etc"
	#     "..".chdir
	#     assert getcwd == "/"
	#
	# Return an error object in case of error.
	#
	#     assert "/etc".chdir == null
	#     assert "/fail/does no/exist".chdir != null
	#     assert getcwd == "/etc" # unchanger
	fun chdir: nullable Error
	do
		var res = to_cstring.file_chdir
		if res then return null
		var error = new IOError("Cannot change directory to `{self}`: {sys.errno.strerror}")
		return error
	end

	# Return right-most extension (without the dot)
	#
	# Only the last extension is returned.
	# There is no special case for combined extensions.
	#
	#     assert "file.txt".file_extension      == "txt"
	#     assert "file.tar.gz".file_extension   == "gz"
	#
	# For file without extension, `null` is returned.
	# Hoever, for trailing dot, `""` is returned.
	#
	#     assert "file".file_extension          == null
	#     assert "file.".file_extension         == ""
	#
	# The starting dot of hidden files is never considered.
	#
	#     assert ".file.txt".file_extension     == "txt"
	#     assert ".file".file_extension         == null
	fun file_extension: nullable String
	do
		var last_slash = chars.last_index_of('.')
		if last_slash > 0 then
			return substring( last_slash+1, length ).to_s
		else
			return null
		end
	end

	# Returns entries contained within the directory represented by self.
	#
	#     var files = "/etc".files
	#     assert files.has("issue")
	#
	# Returns an empty array in case of error
	#
	#     files = "/etc/issue".files
	#     assert files.is_empty
	#
	# TODO find a better way to handle errors and to give them back to the user.
	fun files: Array[String]
	do
		var res = new Array[String]
		var d = new NativeDir.opendir(to_cstring)
		if d.address_is_null then return res

		loop
			var de = d.readdir
			if de.address_is_null then break
			var name = de.to_s
			if name == "." or name == ".." then continue
			res.add name
		end
		d.closedir

		return res
	end
end

redef class FlatString
	redef fun write_native_to(s)
	do
		s.write_native(items, first_byte, byte_length)
	end

	redef fun file_extension do
		var its = _items
		var p = last_byte
		var c = its[p]
		var st = _first_byte
		while p >= st and c != u'.' do
			p -= 1
			c = its[p]
		end
		if p <= st then return null
		var ls = last_byte
		return new FlatString.with_infos(its, ls - p, p + 1)
	end

	redef fun basename(extension) do
		var s = self
		if is_windows then s = s.replace("\\", "/").as(FlatString)

		var bname
		var l = s.last_byte
		var its = s._items
		var min = s._first_byte
		var sl = u'/'
		while l > min and its[l] == sl do l -= 1
		if l == min then return "/"
		var ns = l
		while ns >= min and its[ns] != sl do ns -= 1
		bname = new FlatString.with_infos(its, l - ns, ns + 1)

		return if extension != null then bname.strip_extension(extension) else bname
	end
end

redef class CString
	private fun file_exists: Bool `{
#ifdef _WIN32
		DWORD attribs = GetFileAttributesA(self);
		return attribs != INVALID_FILE_ATTRIBUTES;
#else
		FILE *hdl = fopen(self,"r");
		if(hdl != NULL){
			fclose(hdl);
		}
		return hdl != NULL;
#endif
	`}

	private fun file_stat: NativeFileStat `{
		struct stat buff;
		if(stat(self, &buff) != -1) {
			struct stat* stat_element;
			stat_element = malloc(sizeof(struct stat));
			return memcpy(stat_element, &buff, sizeof(struct stat));
		}
		return 0;
	`}

	private fun file_lstat: NativeFileStat `{
#ifdef _WIN32
		// FIXME use a higher level abstraction to support WIN32
		return NULL;
#else
		struct stat* stat_element;
		int res;
		stat_element = malloc(sizeof(struct stat));
		res = lstat(self, stat_element);
		if (res == -1) return NULL;
		return stat_element;
#endif
	`}

	private fun file_mkdir(mode: Int): Bool `{
#ifdef _WIN32
		return !mkdir(self);
#else
		return !mkdir(self, mode);
#endif
	`}

	private fun rmdir: Bool `{ return !rmdir(self); `}

	private fun file_delete: Bool `{
		return remove(self) == 0;
	`}

	private fun file_chdir: Bool `{ return !chdir(self); `}

	private fun file_realpath: CString `{
#ifdef _WIN32
		DWORD len = GetFullPathName(self, 0, NULL, NULL);
		char *buf = malloc(len+1); // FIXME don't leak memory
		len = GetFullPathName(self, len+1, buf, NULL);
		return buf;
#else
		return realpath(self, NULL);
#endif
	`}
end

# This class is system dependent ... must reify the vfs
private extern class NativeFileStat `{ struct stat * `}

	# Returns the permission bits of file
	fun mode: Int `{ return self->st_mode; `}

	# Returns the last access time
	fun atime: Int `{ return self->st_atime; `}

	# Returns the last status change time
	fun ctime: Int `{ return self->st_ctime; `}

	# Returns the last modification time
	fun mtime: Int `{ return self->st_mtime; `}

	# Returns the size
	fun size: Int `{ return self->st_size; `}

	# Returns true if it is a regular file (not a device file, pipe, sockect, ...)
	fun is_reg: Bool `{ return S_ISREG(self->st_mode); `}

	# Returns true if it is a directory
	fun is_dir: Bool `{ return S_ISDIR(self->st_mode); `}

	# Returns true if it is a character device
	fun is_chr: Bool `{ return S_ISCHR(self->st_mode); `}

	# Returns true if it is a block device
	fun is_blk: Bool `{ return S_ISBLK(self->st_mode); `}

	# Returns true if the type is fifo
	fun is_fifo: Bool `{ return S_ISFIFO(self->st_mode); `}

	# Returns true if the type is a link
	fun is_lnk: Bool `{
#ifdef _WIN32
	return 0;
#else
	return S_ISLNK(self->st_mode);
#endif
	`}

	# Returns true if the type is a socket
	fun is_sock: Bool `{
#ifdef _WIN32
	return 0;
#else
	return S_ISSOCK(self->st_mode);
#endif
	`}
end

# Instance of this class are standard FILE * pointers
private extern class NativeFile `{ FILE* `}
	fun io_read(buf: CString, len: Int): Int `{
		return fread(buf, 1, len, self);
	`}

	fun io_write(buf: CString, from, len: Int): Int `{
		size_t res = fwrite(buf+from, 1, len, self);
#ifdef _WIN32
		// Force flushing buffer because end of line does not trigger a flush
		fflush(self);
#endif
		return (long)res;
	`}

	fun write_byte(value: Int): Int `{
		unsigned char b = (unsigned char)value;
		return fwrite(&b, 1, 1, self);
	`}

	fun io_close: Int `{ return fclose(self); `}

	fun file_stat: NativeFileStat `{
		struct stat buff;
		if(fstat(fileno(self), &buff) != -1) {
			struct stat* stat_element;
			stat_element = malloc(sizeof(struct stat));
			return memcpy(stat_element, &buff, sizeof(struct stat));
		}
		return 0;
	`}

	fun ferror: Bool `{ return ferror(self); `}

	fun feof: Bool `{ return feof(self); `}

	fun fileno: Int `{ return fileno(self); `}

	# Flushes the buffer, forcing the write operation
	fun flush: Int `{ return fflush(self); `}

	# Used to specify how the buffering will be handled for the current stream.
	fun set_buffering_type(buf_length, mode: Int): Int `{
		return setvbuf(self, NULL, (int)mode, buf_length);
	`}

	new io_open_read(path: CString) `{ return fopen(path, "r"); `}

	new io_open_write(path: CString) `{ return fopen(path, "w"); `}

	new native_stdin `{ return stdin; `}

	new native_stdout `{ return stdout; `}

	new native_stderr `{ return stderr; `}
end

# Standard `DIR*` pointer
private extern class NativeDir `{ DIR* `}

	# Open a directory
	new opendir(path: CString) `{ return opendir(path); `}

	# Close a directory
	fun closedir `{ closedir(self); `}

	# Read the next directory entry
	fun readdir: CString `{
		struct dirent *de;
		de = readdir(self);
		if (!de) return NULL;
		return de->d_name;
	`}
end

redef class Sys

	# Standard input
	var stdin: PollableReader = new Stdin is protected writable, lazy

	# Standard output
	var stdout: Writer = new Stdout is protected writable, lazy

	# Standard output for errors
	var stderr: Writer = new Stderr is protected writable, lazy

	# Enumeration for buffer mode full (flushes when buffer is full)
	fun buffer_mode_full: Int `{ return _IOFBF; `}

	# Enumeration for buffer mode line (flushes when a `\n` is encountered)
	fun buffer_mode_line: Int `{ return _IONBF; `}

	# Enumeration for buffer mode none (flushes ASAP when something is written)
	fun buffer_mode_none: Int `{ return _IOLBF; `}

	# returns first available stream to read or write to
	# return null on interruption (possibly a signal)
	protected fun poll( streams : Sequence[FileStream] ) : nullable FileStream
	do
		var in_fds = new Array[Int]
		var out_fds = new Array[Int]
		var fd_to_stream = new HashMap[Int,FileStream]
		for s in streams do
			var fd = s.fd
			if s isa FileReader then in_fds.add( fd )
			if s isa FileWriter then out_fds.add( fd )

			fd_to_stream[fd] = s
		end

		var polled_fd = intern_poll( in_fds, out_fds )

		if polled_fd == null then
			return null
		else
			return fd_to_stream[polled_fd]
		end
	end

	private fun intern_poll(in_fds: Array[Int], out_fds: Array[Int]): nullable Int
	import Array[Int].length, Array[Int].[], Int.as(nullable Int) `{
#ifndef _WIN32
		// FIXME use a higher level abstraction to support WIN32

		int in_len, out_len, total_len;
		struct pollfd *c_fds;
		int i;
		int first_polled_fd = -1;
		int result;

		in_len = (int)Array_of_Int_length( in_fds );
		out_len = (int)Array_of_Int_length( out_fds );
		total_len = in_len + out_len;
		c_fds = malloc( sizeof(struct pollfd) * total_len );

		/* input streams */
		for ( i=0; i<in_len; i ++ ) {
			int fd = (int)Array_of_Int__index( in_fds, i );

			c_fds[i].fd = fd;
			c_fds[i].events = POLLIN;
		}

		/* output streams */
		for ( i=0; i<out_len; i ++ ) {
			int fd = (int)Array_of_Int__index( out_fds, i );

			c_fds[i].fd = fd;
			c_fds[i].events = POLLOUT;
		}

		/* poll all fds, unlimited timeout */
		result = poll( c_fds, total_len, -1 );

		if ( result > 0 ) {
			/* analyse results */
			for ( i=0; i<total_len; i++ )
				if ( c_fds[i].revents & c_fds[i].events || /* awaited event */
					 c_fds[i].revents & POLLHUP ) /* closed */
				{
					first_polled_fd = c_fds[i].fd;
					break;
				}

			return Int_as_nullable( first_polled_fd );
		}
		else if ( result < 0 )
			fprintf( stderr, "Error in Stream:poll: %s\n", strerror( errno ) );
#endif

		return null_Int();
	`}

end

# Print `objects` on the standard output (`stdout`).
fun printn(objects: Object...)
do
	sys.stdout.write(objects.plain_to_s)
end

# Print an `object` on the standard output (`stdout`) and add a newline.
fun print(object: Object)
do
	sys.stdout.write(object.to_s)
	sys.stdout.write("\n")
end

# Print `object` on the error output (`stderr` or a log system)
fun print_error(object: Object)
do
	sys.stderr.write object.to_s
	sys.stderr.write "\n"
end

# Read a character from the standard input (`stdin`).
fun getc: Char
do
	var c = sys.stdin.read_char
	if c == null then return '\1'
	return c
end

# Read a line from the standard input (`stdin`).
fun gets: String
do
	return sys.stdin.read_line
end

# Return the working (current) directory
fun getcwd: String do return native_getcwd.to_s

private fun native_getcwd: CString `{ return getcwd(NULL, 0); `}
lib/core/file.nit:15,1--1726,64