<commit_before>package pman.format.xspf;

import tannus.ds.*;
import tannus.io.*;
import tannus.sys.*;

import pman.core.*;
import pman.media.*;

import Xml;
import Xml.XmlType;
import Slambda.fn;

using StringTools;
using Lambda;
using tannus.ds.ArrayTools;
using tannus.ds.StringUtils;
using Slambda;
using pman.media.MediaTools;

class Reader {
	/* Constructor Function */
	public function new():Void {

	}

/* === Instance Methods === */

	/**
	  * read the given String as an xspf playlist
	  */
	public function read(s : String):Playlist {
		root = Xml.parse( s );
		playlist = new Playlist();

		walk( root );

		return playlist;
	}

	private function element(e : Xml):Void {
		switch (e.nodeName.toLowerCase()) {
			case 'playlist', 'tracklist':
				walk( e );

			case 'track':
				trackNode( e );

			default:
				null;
		}
	}

	private function trackNode(e : Xml):Void {
		var subs = e.elements();
		var info:Map<String, String> = new Map();
		for (n in subs) {
			info[n.nodeName] = text( n );
		}
		track( info );
	}

	private function track(info : Map<String, String>):Void {
		var t = info['location'].trim().parseToTrack();
		playlist.push( t );
	}

	private function node(x : Xml):Void {
		switch ( x.nodeType ) {
			case Element:
				element( x );

			default:
				null;
		}
	}

	private function walk(xmlNode : Xml):Void {
		for (n in xmlNode) {
			node( n );
		}
	}

	/**
	  * get the textual value of the given node
	  */
	private static function text(x : Xml):String {
		switch ( x.nodeType ) {
			case CData, PCData:
				return x.nodeValue;

			case Element:
				return (x.array().map(text).join(''));

			default:
				return '';
		}
	}

/* === Instance Fields === */

	private var root : Xml;
	private var playlist : Playlist;
}<commit_msg>completely reimplemented pman.format.xspf.Reader as a subclass of edis.xml.BaseXmlParser<commit_after>package pman.format.xspf;

import tannus.ds.*;
import tannus.io.*;
import tannus.sys.*;

import pman.bg.media.*;
import pman.format.xspf.Data;

import edis.xml.*;

import Xml;
import Xml.XmlType;
import Slambda.fn;
import tannus.io.Ptr.*;

import haxe.macro.Expr;

using StringTools;
using Lambda;
using tannus.ds.ArrayTools;
using tannus.ds.StringUtils;
using Slambda;
using pman.bg.URITools;
using pman.bg.PathTools;
using edis.xml.XmlTools;

@:noPackageRestrict
class Reader extends BaseXmlParser {
	/* Constructor Function */
	public function new():Void {
	    super();
	}

/* === Instance Methods === */

    public function parseString(xmlString: String):Data {
        doc = null;
        handleString( xmlString );
        return doc;
    }

    /**
      * pull from a ByteArray
      */
    public function read(data: ByteArray):Data {
        return parseString(data.toString());
    }

    /**
      * set up the parsing procedures
      */
    override function setup():Void {
        on('playlist', parsePlaylistNode);
        onElement(function(node) {
            trace( node );
        });
    }

    /**
      * handles parsing of the playlist node
      */
    private function parsePlaylistNode(playlist: FunctionalNodeHandler):Void {
        doc = new Data();
        var txt = playlist.childGetText.bind(_, _);
        
        txt('title', fn(doc.title = _));
        txt('creator', fn(doc.creator = _));
        txt('annotation', fn(doc.annotation = _));
        txt('info', fn(doc.info = _));
        //TODO etc...

        playlist.on('trackList', parseTrackListNode);
    }

    /**
      * handles parsing of the trackList node
      */
    private function parseTrackListNode(l: FunctionalNodeHandler):Void {
        l.on('track', function(_node) {
            parseTrackNode(_node, function(t: Null<DataTrack>) {
                if (t != null) {
                    doc.addTrack( t );
                }
            });
        });
    }

    /**
      * parses each <track/> node
      */
    private function parseTrackNode(tn:FunctionalNodeHandler, f:Null<DataTrack>->Void):Void {
        var txt = tn.childGetText.bind(_, _), num = tn.childGetTextAsFloat.bind(_, _), inum = tn.childGetTextAsInt.bind(_, _);
        var track = doc.createTrack();

        txt('title', setr(track.title));
        txt('location', uri->track.addLocation( uri ));
        inum('duration', setr(track.duration));

        tn.then(function() {
            if (track.locations.hasContent()) {
                f( track );
            }
            else {
                f( null );
            }
        });
    }

    //private static macro function ex(f:Expr, ctx:Expr, id:Expr) {
        //return macro ($f('$id', x->$ctx.$id=x));
    //}

    private var doc: Data;
}
{'fraction_non_alphanumeric': 0.14291863969005597, 'fraction_numerical': 0.0, 'mean_word_length': 2.46274217585693, 'pattern_counts': {'":': 0, '<': 8, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 7}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3721077', 'n_tokens_mistral': 1611, 'n_tokens_neox': 1497, 'n_words': 356}