Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1754

Show
Ignore:
Timestamp:
07/13/10 01:12:56 (14 years ago)
Author:
rsinfu
Message:

[devel] stub for LockingNativeTextWriter?

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/devel/stdio-native-codeset/phobos/std/stdio.d

    r1725 r1754  
    23562356    for (int c; (c = FGETC(fp)) != -1; ) 
    23572357    { 
    23582358        buf ~= cast(char)c; 
    23592359        if (c == terminator) 
    23602360            break; 
    23612361    } 
    23622362    if (ferror(fps)) 
    23632363        StdioException(); 
    23642364    return buf.length; 
    23652365} 
     2366 
     2367__EOF__ 
     2368 
     2369import std.variant : Algebraic; 
     2370 
     2371version (Windows) private 
     2372{ 
     2373    import core.sys.windows.windows; 
     2374    import std.windows.syserror; 
     2375 
     2376    version (DigitalMars) 
     2377    { 
     2378        extern(C) extern __gshared HANDLE[_NFILE] _osfhnd; 
     2379        @safe HANDLE peekHANDLE(FILE* f) { return _osfhnd[f._file]; } 
     2380        version = WITH_WINDOWS_CONSOLE; 
     2381    } 
     2382 
     2383    /* 
     2384     * Returns $(D true) if $(D handle) is a valid console handle that 
     2385     * characters can be written to. 
     2386     */ 
     2387    @trusted bool isConsole(HANDLE handle) 
     2388    { 
     2389        DWORD dummy; 
     2390 
     2391        return GetConsoleMode(handle, &dummy) && 
     2392            WriteConsoleA(handle, "\0".ptr, 0, null, null); 
     2393    } 
     2394} 
     2395 
     2396 
     2397/** 
     2398$(D output range) that locks the file and provides writing to the 
     2399file in the native codeset. 
     2400 */ 
     2401struct LockingNativeTextWriter 
     2402{ 
     2403    private 
     2404    { 
     2405        alias NativeTextEncoder!(UnsharedNarrowWriter) NativeWriter; 
     2406        alias WideTextEncoder!(UnsharedWideWriter) WideWriter; 
     2407 
     2408        version (Windows) 
     2409        { 
     2410            alias WideTextEncoder!(WindowsWideConsoleWriter) ConsoleWideWriter; 
     2411            alias Algebraic!(NativeWriter, WideWriter, ConsoleWideWriter) 
     2412                                                       Writer; 
     2413        } 
     2414        else 
     2415        { 
     2416            alias Algebraic!(NativeWriter, WideWriter) Writer; 
     2417        } 
     2418 
     2419        File   _file; 
     2420        Writer _writer; 
     2421    } 
     2422 
     2423    /** 
     2424     * Constructs a $(D LockingNativeTextWriter) object. 
     2425     * 
     2426     * Params: 
     2427     *   file = 
     2428     *     An open $(D File) to write in. 
     2429     * 
     2430     * Throws: 
     2431     * $(UL 
     2432     *   $(LI $(D enforcement) fails if $(D file) is not open.) 
     2433     *   $(LI $(D enforcement) fails if there is no safe mean to 
     2434     *        convert UTF to the native codeset.) 
     2435     * ) 
     2436     */ 
     2437    @trusted this(File file) 
     2438    { 
     2439        enforce(file.isOpen); 
     2440        swap(_file, file); 
     2441        FLOCK(_file.p.handle); 
     2442        auto handle = cast(_iobuf*) _file.p.handle; 
     2443 
     2444        // prefer ConsoleWideWriter 
     2445        version (Windows) static if (is(typeof(peekHANDLE) == function)) 
     2446        { 
     2447            HANDLE console = peekHANDLE(_file.p.handle); 
     2448 
     2449            if (isConsole(console) && WindowsWideConsoleWriter.supported) 
     2450            { 
     2451                _file.flush(); // need to sync 
     2452                _writer = ConsoleWideWriter(WindowsWideConsoleWriter(console)); 
     2453                return; 
     2454            } 
     2455        } 
     2456 
     2457        if (fwide(handle, 0) > 0) 
     2458            _writer = WideWriter(UnsharedWideWriter(handle)); 
     2459        else 
     2460            _writer = NativeWriter(UnsharedNarrowWriter(handle)); 
     2461    } 
     2462 
     2463    @trusted this(this) 
     2464    { 
     2465        FLOCK(_file.p.handle); 
     2466    } 
     2467 
     2468    @trusted ~this() 
     2469    { 
     2470        if (_file.isOpen) 
     2471            FUNLOCK(_file.p.handle); 
     2472    } 
     2473 
     2474    @trusted void opAssign(LockingNativeTextWriter rhs) 
     2475    { 
     2476        swap(this, rhs); 
     2477    } 
     2478 
     2479    /// Range primitive implementation. 
     2480    @safe void put(T)(T e) 
     2481    { 
     2482        _writer.put(e); 
     2483    } 
     2484} 
     2485 
     2486 
     2487/* 
     2488Range that writes multibyte string to a locked, byte-oriented FILE* stream. 
     2489 */ 
     2490private struct UnsharedNarrowWriter 
     2491{ 
     2492    private _iobuf* _handle; 
     2493 
     2494    @trusted void put(in ubyte[] str) 
     2495    { 
     2496        for (const(ubyte)[] inbuf = str; inbuf.length > 0; ) 
     2497        { 
     2498            immutable nwritten = fwrite( 
     2499                    inbuf.ptr, 1, inbuf.length, cast(shared) _handle); 
     2500            if (nwritten == inbuf.length) 
     2501                break; 
     2502            switch (errno) 
     2503            { 
     2504            case EINTR: 
     2505                str = str[nwritten .. $]; 
     2506                continue; 
     2507 
     2508            default: 
     2509                throw new StdioException(null); 
     2510            } 
     2511        } 
     2512    } 
     2513} 
     2514 
     2515 
     2516/* 
     2517Range that writes wide string to a locked, wide-oriented FILE* stream. 
     2518 */ 
     2519private struct UnsharedWideWriter 
     2520{ 
     2521    private _iobuf* _handle; 
     2522 
     2523    @trusted void put(wchar_t ch) 
     2524    { 
     2525        while (FPUTWC(ch, _handle) == WEOF) 
     2526        { 
     2527            switch (errno) 
     2528            { 
     2529            case EINTR: 
     2530                continue; 
     2531            default: 
     2532                throw new StdioException(null); 
     2533            } 
     2534        } 
     2535    } 
     2536 
     2537    @trusted void put(in wchar_t[] str) 
     2538    { 
     2539        foreach (ch; str) 
     2540        { 
     2541            while (FPUTWC(ch, _handle) == WEOF) 
     2542            { 
     2543                switch (errno) 
     2544                { 
     2545                case EINTR: 
     2546                    continue; 
     2547                default: 
     2548                    throw new StdioException(null); 
     2549                } 
     2550            } 
     2551        } 
     2552    } 
     2553} 
     2554 
     2555 
     2556/* 
     2557Range that writes wide string to a Windows console. 
     2558 */ 
     2559version (Windows) 
     2560private struct WindowsWideConsoleWriter 
     2561{ 
     2562    private HANDLE _console; 
     2563 
     2564    @trusted void put(WCHAR wc) 
     2565    { 
     2566        if (!indirectWriteConsoleW(_console, &wc, 1, null, null)) 
     2567            throw new /+StdioException+/Exception( 
     2568                sysErrorString(GetLastError())); 
     2569    } 
     2570 
     2571    @trusted void put(in WCHAR[] str) 
     2572    { 
     2573        for (const(WCHAR)[] outbuf = str; outbuf.length > 0; ) 
     2574        { 
     2575            DWORD nwritten; 
     2576 
     2577            if (!indirectWriteConsoleW(_console, 
     2578                    outbuf.ptr, outbuf.length, &nwritten, null)) 
     2579                throw new /+StdioException+/Exception( 
     2580                    sysErrorString(GetLastError())); 
     2581            outbuf = outbuf[nwritten .. $]; 
     2582        } 
     2583    } 
     2584 
     2585 
     2586    /* 
     2587     * Returns $(D true) if $(D WriteConsoleW) is supported under the 
     2588     * running environment. 
     2589     */ 
     2590    static @safe @property bool supported() 
     2591    { 
     2592        return indirectWriteConsoleW !is null; 
     2593    } 
     2594 
     2595    private static __gshared typeof(&WriteConsoleW) indirectWriteConsoleW; 
     2596 
     2597    shared static this() 
     2598    { 
     2599        indirectWriteConsoleW = cast(typeof(&WriteConsoleW)) 
     2600            GetProcAddress(GetModuleHandleA("kernel32.dll"), "WriteConsoleW"); 
     2601    } 
     2602} 
     2603