text:
layout: page
title: Excellent Omega Corporation Award Ceremony
date: 2016-05-24
author: Jane Melendez
tags: weekly links, java
status: published
summary: Morbi feugiat tristique arcu, vel.
banner: images/banner/meeting-01.jpg
booking:
  startDate: 10/05/2019
  endDate: 10/10/2019
  ctyhocn: MSQHXHX
  groupCode: EOCAC
published: true
---
Sed nibh augue, pharetra vitae bibendum eget, euismod vitae nisl. Donec finibus a urna ac aliquam. Nulla eu scelerisque metus. Aliquam a molestie nibh. Sed malesuada suscipit lorem sagittis pretium. Maecenas risus augue, consectetur sed felis sit amet, consectetur tempor nibh. In et nisl ut massa imperdiet viverra id ac eros.
Sed tempus at neque at tempor. Suspendisse vel mi condimentum, ullamcorper enim et, eleifend nunc. Vestibulum non egestas diam, vel accumsan augue. Cras blandit orci sed arcu sodales hendrerit. Integer orci diam, bibendum a nibh et, facilisis pretium eros. Phasellus lobortis tincidunt enim sed facilisis. In scelerisque odio massa, quis ultrices nisl vehicula sed. Nulla placerat commodo nulla at sagittis. Praesent in nibh malesuada, fringilla ex in, pulvinar turpis. Fusce finibus dignissim lectus, quis pharetra odio semper non. Nunc commodo ultricies eleifend. Phasellus faucibus risus vel magna aliquam, a ultrices nisl tristique. Vestibulum vestibulum elementum magna sed fringilla. Aenean congue auctor posuere.

* Ut rhoncus sapien ac sem maximus interdum
* Vestibulum vitae justo sed orci facilisis vulputate
* Vestibulum cursus justo ut velit porta fringilla
* Proin et sem vitae turpis blandit maximus.

Maecenas felis lorem, finibus ut elit sit amet, volutpat aliquam erat. Maecenas sed nisi non magna venenatis fringilla. Donec condimentum lobortis mi vel mattis. Morbi nec eleifend lacus. Ut non ex dui. Nulla nisi mi, porttitor vitae ligula vel, maximus dapibus ante. Vivamus eleifend interdum maximus. Sed vel erat id purus semper porta quis vel purus. Cras cursus arcu dui, sed condimentum libero ornare malesuada. Ut venenatis velit lorem, et dictum tortor mattis nec. Maecenas ultrices, tellus ac blandit rutrum, tellus neque volutpat felis, id viverra nunc risus lacinia ipsum. Maecenas egestas sed sapien non posuere.


text:
use std::fmt::Debug;

use ::base::*;
use bitreader::BitReader;
use bitreader::Result as BitReaderResult;

pub trait Descriptor: Debug {}

pub mod basic;
pub mod dvb;

macro_rules! descriptor_match {
    (
        match $descriptor_tag:ident with $reader:ident {
            $($tag:pat => $T:ty),+
        }
    ) => (
        match $descriptor_tag {
            $(
                $tag => Ok(Box::new(try!(<$T as Deserialize>::deserialize($reader))))
            ),+
        }
    );
}

pub fn deserialize_descriptor(reader: &mut BitReader) -> DeserializationResult<Box<Descriptor>> {
    let mut tag_reader = reader.relative_reader();
    let descriptor_tag = try!(tag_reader.read_u8(8));
    descriptor_match!(
        match descriptor_tag with reader {
            2 => basic::VideoStreamDescriptor,
            3 => basic::AudioStreamDescriptor,
            4 => basic::HierarchyDescriptor,
            5 => basic::RegistrationDescriptor,
            6 => basic::DataStreamAlignmentDescriptor,
            7 => basic::TargetBackgroundGridDescriptor,
            8 => basic::VideoWindowDescriptor,
            9 => basic::CaDescriptor,
            10 => basic::Iso639LanguageDescriptor,
            11 => basic::SystemClockDescriptor,
            12 => basic::MultiplexBufferUtilizationDescriptor,
            13 => basic::CopyrightDescriptor,
            14 => basic::MaximumBitrateDescriptor,
            15 => basic::PrivateDataIndicatorDescriptor,
            16 => basic::SmoothingBufferDescriptor,
            17 => basic::StdDescriptor,
            18 => basic::IbpDescriptor,

            27 => basic::Mpeg4VideoDescriptor,
            28 => basic::Mpeg4AudioDescriptor,
            29 => basic::IodDescriptor,
            30 => basic::SlDescriptor,
            31 => basic::FmcDescriptor,
            32 => basic::ExternalEsIdDescriptor,
            33 => basic::MuxCodeDescriptor,
            34 => basic::FmxBufferSizeDescriptor,
            35 => basic::MultiplexBufferDescriptor,

            0x40 => dvb::NetworkNameDescriptor,
            0x41 => dvb::ServiceListDescriptor,
            0x42 => dvb::StuffingDescriptor,
            0x43 => dvb::SatelliteDeliverySystemDescriptor,
            0x44 => dvb::CableDeliverySystemDescriptor,
            0x45 => dvb::VbiDataDescriptor,
            0x46 => dvb::VbiTeletextDescriptor,
            0x47 => dvb::BouquetNameDescriptor,
            0x48 => dvb::ServiceDescriptor,
            0x49 => dvb::CountryAvailabilityDescriptor,
            0x4a => dvb::LinkageDescriptor,
            0x4b => dvb::NvodReferenceDescriptor,
            0x4c => dvb::TimeShiftedServiceDescriptor,
            0x4d => dvb::ShortEventDescriptor,
            0x4e => dvb::ExtendedEventDescriptor,
            0x4f => dvb::TimeShiftedEventDescriptor,
            0x50 => dvb::ComponentDescriptor,
            0x51 => dvb::MosaicDescriptor,
            0x52 => dvb::StreamIdentifierDescriptor,
            0x53 => dvb::CaIdentifierDescriptor,
            0x54 => dvb::ContentDescriptor,
            0x55 => dvb::ParentalRatingDescriptor,
            0x56 => dvb::TeletextDescriptor,
            0x57 => dvb::TelephoneDescriptor,
            0x58 => dvb::LocalTimeOffsetDescriptor,
            0x59 => dvb::SubtitlingDescriptor,
            0x5a => dvb::TerrestrialDeliverySystemDescriptor,
            0x5b => dvb::MultilingualNetworkNameDescriptor,
            0x5c => dvb::MultilingualBouquetNameDescriptor,
            0x5d => dvb::MultilingualServiceNameDescriptor,
            0x5e => dvb::MultilingualComponentDescriptor,
            0x5f => dvb::PrivateDataSpecifierDescriptor,
            0x60 => dvb::ServiceMoveDescriptor,
            0x61 => dvb::ShortSmoothingBufferDescriptor,
            0x62 => dvb::FrequencyListDescriptor,
            0x63 => dvb::PartialTransportStreamDescriptor,
            0x64 => dvb::DataBroadcastDescriptor,
            0x65 => dvb::ScramblingDescriptor,
            0x66 => dvb::DataBroadcastIdDescriptor,
            0x67 => dvb::TransportStreamDescriptor,
            0x68 => dvb::DsngDescriptor,
            0x69 => dvb::PdcDescriptor,
            0x6a => dvb::Ac3Descriptor,
            0x6b => dvb::AncillaryDataDescriptor,
            0x6c => dvb::CellListDescriptor,
            0x6d => dvb::CellFrequencyLinkDescriptor,
            0x6e => dvb::AnnouncementSupportDescriptor,
            0x6f => dvb::ApplicationSignallingDescriptor,
            0x70 => dvb::AdaptationFieldDataDescriptor,
            0x71 => dvb::ServiceIdentifierDescriptor,
            0x72 => dvb::ServiceAvailabilityDescriptor,
            0x73 => dvb::DefaultAuthorityDescriptor,
            0x74 => dvb::RelatedContentDescriptor,
            0x75 => dvb::TvaIdDescriptor,
            0x76 => dvb::ContentIdentifierDescriptor,
            0x77 => dvb::TimeSliceFecIdentifierDescriptor,
            0x78 => dvb::EcmRepetitionRateDescriptor,
            0x79 => dvb::S2SatelliteDeliverySystemDescriptor,
            0x7a => dvb::EnhancedAc3Descriptor,
            0x7b => dvb::DtsDescriptor,
            0x7c => dvb::AacDescriptor,
            0x7d => dvb::XaitLocationDescriptor,
            0x7e => dvb::FtaDescriptor,
            0x7f => dvb::ExtensionDescriptor,

            _ => basic::UnknownDescriptor
        }
    )
}

fn bits_remaining(descriptor_length: u8, reader: &BitReader) -> u64 {
    let intro_bits = 16; // descriptor_tag (8 bits) + descriptor_length (8 bits)
    let data_bits = descriptor_length as u64 * 8; // How many data bits after intro bits
    let total_descriptor_bits = intro_bits + data_bits;
    total_descriptor_bits - reader.position() as u64
}

fn repeated_element<T: Deserialize>(descriptor_length: u8, reader: &mut BitReader) -> DeserializationResult<Vec<T>> {
    let bytes_remaining = bits_remaining(descriptor_length, reader) / 8;
    ::base::read_repeated(bytes_remaining as usize, reader)
}

fn repeated_sub_element<T: Deserialize>(element_bytes: u8, reader: &mut BitReader) -> DeserializationResult<Vec<T>> {
    ::base::read_repeated(element_bytes as usize, reader)
}

fn read_tla(reader: &mut BitReader) -> BitReaderResult<String> {
    let mut tla = String::with_capacity(3);
    tla.push(try!(reader.read_u8(8)) as char);
    tla.push(try!(reader.read_u8(8)) as char);
    tla.push(try!(reader.read_u8(8)) as char);
    Ok(tla)
}

redpajama_set_name: RedPajamaGithub


text:
class BLOCK_LIST;
struct Boxa;
struct Pixa;
class DENORM;
class ScrollView;
class STATS;
class TO_BLOCK;

namespace tesseract {

extern BOOL_VAR_H(textord_tabfind_find_tables, false, "run table detection");

class ColPartitionSet;
class ColPartitionSet_LIST;
class ColSegment_LIST;
class ColumnGroup_LIST;
class LineSpacing;
class StrokeWidth;
class TempColumn_LIST;
class EquationDetectBase;

// The ColumnFinder class finds columns in the grid.
class ColumnFinder : public TabFind {
 public:
  // Gridsize is an estimate of the text size in the image. A suitable value
  // is in TO_BLOCK::line_size after find_components has been used to make
  // the blobs.
  // bleft and tright are the bounds of the image (rectangle) being processed.
  // vlines is a (possibly empty) list of TabVector and vertical_x and y are
  // the sum logical vertical vector produced by LineFinder::FindVerticalLines.
  // If cjk_script is true, then broken CJK characters are fixed during
  // layout analysis to assist in detecting horizontal vs vertically written
  // textlines.
  ColumnFinder(int gridsize, const ICOORD& bleft, const ICOORD& tright,
               int resolution, bool cjk_script, double aligned_gap_fraction,
               TabVector_LIST* vlines, TabVector_LIST* hlines,
               int vertical_x, int vertical_y);
  virtual ~ColumnFinder();

  // Accessors for testing
  const DENORM* denorm() const {
    return denorm_;
  }
  const TextlineProjection* projection() const {
    return &projection_;
  }
  void set_cjk_script(bool is_cjk) {
    cjk_script_ = is_cjk;
  }

  // ======================================================================
  // The main function of ColumnFinder is broken into pieces to facilitate
  // optional insertion of orientation and script detection in an efficient
  // way. The calling sequence IS MANDATORY however, whether or not
  // OSD is being used:
  // 1. Construction.
  // 2. SetupAndFilterNoise.
  // 3. IsVerticallyAlignedText.
  // 4. CorrectOrientation.
  // 5. FindBlocks.
  // 6. Destruction. Use of a single column finder for multiple images does not
  //    make sense.
  // Throughout these steps, the ColPartitions are owned by part_grid_, which
  // means that that it must be kept correct. Exception: big_parts_ owns its
  // own ColPartitions.
  // The BLOBNBOXes are owned by the input TO_BLOCK for the whole time, except
  // for a phase in FindBlocks before TransformToBlocks, when they become
  // owned by the ColPartitions. The owner() ColPartition of a BLOBNBOX
  // indicates more of a betrothal for the majority of layout analysis, ie
  // which ColPartition will take ownership when the blobs are release from
  // the input TO_BLOCK. Exception: image_bblobs_ owns the fake blobs that
  // are part of the image regions, as they are not on any TO_BLOCK list.
  // TODO(rays) break up column finder further into smaller classes, as
  // there is a lot more to it than column finding now.
  // ======================================================================

  // Performs initial processing on the blobs in the input_block:
  // Setup the part_grid, stroke_width_, nontext_map_.
  // Obvious noise blobs are filtered out and used to mark the nontext_map_.
  // Initial stroke-width analysis is used to get local text alignment
  // direction, so the textline projection_ map can be setup.
  // On return, IsVerticallyAlignedText may be called (now optionally) to
  // determine the gross textline alignment of the page.
  void SetupAndFilterNoise(PageSegMode pageseg_mode, Pix* photo_mask_pix,
                           TO_BLOCK* input_block);

  // Tests for vertical alignment of text (returning true if so), and generates
  // a list of blobs (in osd_blobs) for orientation and script detection.
  // block is the single block for the whole page or rectangle to be OCRed.
  // Note that the vertical alignment may be due to text whose writing direction
  // is vertical, like say Japanese, or due to text whose writing direction is
  // horizontal but whose text appears vertically aligned because the image is
  // not the right way up.
  // find_vertical_text_ratio should be textord_tabfind_vertical_text_ratio.
  bool IsVerticallyAlignedText(double find_vertical_text_ratio,
                               TO_BLOCK* block, BLOBNBOX_CLIST* osd_blobs);

  // Rotates the blobs and the TabVectors so that the gross writing direction
  // (text lines) are horizontal and lines are read down the page.
  // Applied rotation stored in rotation_.
  // A second rotation is calculated for application during recognition to
  // make the rotated blobs upright for recognition.
  // Subsequent rotation stored in text_rotation_.
  //
  // Arguments:
  //   vertical_text_lines is true if the text lines are vertical.
  //   recognition_rotation [0..3] is the number of anti-clockwise 90 degree
  //   rotations from osd required for the text to be upright and readable.
  void CorrectOrientation(TO_BLOCK* block, bool vertical_text_lines,
                          int recognition_rotation);

  // Finds blocks of text, image, rule line, table etc, returning them in the
  // blocks and to_blocks
  // (Each TO_BLOCK points to the basic BLOCK and adds more information.)
  // Image blocks are generated by a combination of photo_mask_pix (which may
  // NOT be NULL) and the rejected text found during preliminary textline
  // finding.
  // The input_block is the result of a call to find_components, and contains
  // the blobs found in the image or rectangle to be OCRed. These blobs will be
  // removed and placed in the output blocks, while unused ones will be deleted.
  // If single_column is true, the input is treated as single column, but
  // it is still divided into blocks of equal line spacing/text size.
  // scaled_color is scaled down by scaled_factor from the input color image,
  // and may be NULL if the input was not color.
  // grey_pix is optional, but if present must match the photo_mask_pix in size,
  // and must be a *real* grey image instead of binary_pix * 255.
  // thresholds_pix is expected to be present iff grey_pix is present and
  // can be an integer factor reduction of the grey_pix. It represents the
  // thresholds that were used to create the binary_pix from the grey_pix.
  // Small blobs that confuse the segmentation into lines are placed into
  // diacritic_blobs, with the intention that they be put into the most
  // appropriate word after the rest of layout analysis.
  // Returns -1 if the user hits the 'd' key in the blocks window while running
  // in debug mode, which requests a retry with more debug info.
  int FindBlocks(PageSegMode pageseg_mode, Pix* scaled_color, int scaled_factor,
                 TO_BLOCK* block, Pix* photo_mask_pix, Pix* thresholds_pix,
                 Pix* grey_pix, BLOCK_LIST* blocks,
                 BLOBNBOX_LIST* diacritic_blobs, TO_BLOCK_LIST* to_blocks);

  // Get the rotation required to deskew, and its inverse rotation.
  void GetDeskewVectors(FCOORD* deskew, FCOORD* reskew);

  // Set the equation detection pointer.
  void SetEquationDetect(EquationDetectBase* detect);

 private:
  // Displays the blob and block bounding boxes in a window called Blocks.
  void DisplayBlocks(BLOCK_LIST* blocks);
  // Displays the column edges at each grid y coordinate defined by
  // best_columns_.
  void DisplayColumnBounds(PartSetVector* sets);

  ////// Functions involved in determining the columns used on the page. /////

  // Sets up column_sets_ (the determined column layout at each horizontal
  // slice). Returns false if the page is empty.
  bool MakeColumns(bool single_column);
  // Attempt to improve the column_candidates by expanding the columns
  // and adding new partitions from the partition sets in src_sets.
  // Src_sets may be equal to column_candidates, in which case it will
  // use them as a source to improve themselves.
  void ImproveColumnCandidates(PartSetVector* src_sets,
                               PartSetVector* column_sets);
  // Prints debug information on the column candidates.
  void PrintColumnCandidates(const char* title);
  // Finds the optimal set of columns that cover the entire image with as
  // few changes in column partition as possible.
  // Returns true if any part of the page is multi-column.
  bool AssignColumns(const PartSetVector& part_sets);
  // Finds the biggest range in part_sets_ that has no assigned column, but
  // column assignment is possible.
  bool BiggestUnassignedRange(int set_count, const bool* any_columns_possible,
                              int* start, int* end);
  // Finds the modal compatible column_set_ index within the given range.
  int RangeModalColumnSet(int** column_set_costs, const int* assigned_costs,
                          int start, int end);
  // Given that there are many column_set_id compatible columns in the range,
  // shrinks the range to the longest contiguous run of compatibility, allowing
  // gaps where no columns are possible, but not where competing columns are
  // possible.
  void ShrinkRangeToLongestRun(int** column_set_costs,
                               const int* assigned_costs,
                               const bool* any_columns_possible,
                               int column_set_id,
                               int* best_start, int* best_end);
  // Moves start in the direction of step, upto, but not including end while
  // the only incompatible regions are no more than kMaxIncompatibleColumnCount
  // in size, and the compatible regions beyond are bigger.
  void ExtendRangePastSmallGaps(int** column_set_costs,
                                const int* assigned_costs,
                                const bool* any_columns_possible,
                                int column_set_id,
                                int step, int end, int* start);
  // Assigns the given column_set_id to the part_sets_ in the given range.
  void AssignColumnToRange(int column_set_id, int start, int end,
                           int** column_set_costs, int* assigned_costs);

  // Computes the mean_column_gap_.
  void ComputeMeanColumnGap(bool any_multi_column);

  //////// Functions that manipulate ColPartitions in the part_grid_ /////
  //////// to split, merge, find margins, and find types.  //////////////

  // Hoovers up all un-owned blobs and deletes them.
  // The rest get released from the block so the ColPartitions can pass
  // ownership to the output blocks.
  void ReleaseBlobsAndCleanupUnused(TO_BLOCK* block);
  // Splits partitions that cross columns where they have nothing in the gap.
  void GridSplitPartitions();
  // Merges partitions where there is vertical overlap, within a single column,
  // and the horizontal gap is small enough.
  void GridMergePartitions();
  // Inserts remaining noise blobs into the most applicable partition if any.
  // If there is no applicable partition, then the blobs are deleted.
  void InsertRemainingNoise(TO_BLOCK* block);
  // Remove partitions that come from horizontal lines that look like
  // underlines, but are not part of a table.
  void GridRemoveUnderlinePartitions();
  // Add horizontal line separators as partitions.
  void GridInsertHLinePartitions();
  // Add vertical line separators as partitions.
  void GridInsertVLinePartitions();
  // For every ColPartition in the grid, sets its type based on position
  // in the columns.
  void SetPartitionTypes();
  // Only images remain with multiple types in a run of partners.
  // Sets the type of all in the group to the maximum of the group.
  void SmoothPartnerRuns();

  //////// Functions that make the final output blocks             ///////

  // Helper functions for TransformToBlocks.
  // Add the part to the temp list in the correct order.
  void AddToTempPartList(ColPartition* part, ColPartition_CLIST* temp_list);
  // Add everything from the temp list to the work_set assuming correct order.
  void EmptyTempPartList(ColPartition_CLIST* temp_list,
                         WorkingPartSet_LIST* work_set);

  // Transform the grid of partitions to the output blocks.
  void TransformToBlocks(BLOCK_LIST* blocks, TO_BLOCK_LIST* to_blocks);

  // Reflect the blob boxes (but not the outlines) in the y-axis so that
  // the blocks get created in the correct RTL order. Rotates the blobs
  // in the input_block and the bblobs list.
  // The reflection is undone in RotateAndReskewBlocks by
  // reflecting the blocks themselves, and then recomputing the blob bounding
  //  boxes.
  void ReflectForRtl(TO_BLOCK* input_block, BLOBNBOX_LIST* bblobs);

  // Undo the deskew that was done in FindTabVectors, as recognition is done
  // without correcting blobs or blob outlines for skew.
  // Reskew the completed blocks to put them back to the original rotated coords
  // that were created by CorrectOrientation.
  // If the input_is_rtl, then reflect the blocks in the y-axis to undo the
  // reflection that was done before FindTabVectors.
  // Blocks that were identified as vertical text (relative to the rotated
  // coordinates) are further rotated so the text lines are horizontal.
  // blob polygonal outlines are rotated to match the position of the blocks
  // that they are in, and their bounding boxes are recalculated to be accurate.
  // Record appropriate inverse transformations and required
  // classifier transformation in the blocks.
  void RotateAndReskewBlocks(bool input_is_rtl, TO_BLOCK_LIST* to_blocks);

  // Computes the rotations for the block (to make textlines horizontal) and
  // for the blobs (for classification) and sets the appropriate members
  // of the given block.
  // Returns the rotation that needs to be applied to the blobs to make
  // them sit in the rotated block.
  FCOORD ComputeBlockAndClassifyRotation(BLOCK* block);

  // If true then the page language is cjk, so it is safe to perform
  // FixBrokenCJK.
  bool cjk_script_;
  // The minimum gutter width to apply for finding columns.
  // Modified when vertical text is detected to prevent detection of
  // vertical text lines as columns.
  int min_gutter_width_;
  // The mean gap between columns over the page.
  int mean_column_gap_;
  // Config param saved at construction time. Modifies min_gutter_width_ with
  // vertical text to prevent detection of vertical text as columns.
  double tabfind_aligned_gap_fraction_;
  // The rotation vector needed to convert original coords to deskewed.
  FCOORD deskew_;
  // The rotation vector needed to convert deskewed back to original coords.
  FCOORD reskew_;
  // The rotation vector used to rotate vertically oriented pages.
  FCOORD rotation_;
  // The rotation vector needed to convert the rotated back to original coords.
  FCOORD rerotate_;
  // The additional rotation vector needed to rotate text for recognition.
  FCOORD text_rotation_;
  // The column_sets_ contain the ordered candidate ColPartitionSets that
  // define the possible divisions of the page into columns.
  PartSetVector column_sets_;
  // A simple array of pointers to the best assigned column division at
  // each grid y coordinate.
  ColPartitionSet** best_columns_;
  // The grid used for creating initial partitions with strokewidth.
  StrokeWidth* stroke_width_;
  // The grid used to hold ColPartitions after the columns have been determined.
  ColPartitionGrid part_grid_;
  // List of ColPartitions that are no longer needed after they have been
  // turned into regions, but are kept around because they are referenced
  // by the part_grid_.
  ColPartition_LIST good_parts_;
  // List of ColPartitions that are big and might be dropcap or vertically
  // joined.
  ColPartition_LIST big_parts_;
  // List of ColPartitions that have been declared noise.
  ColPartition_LIST noise_parts_;
  // The fake blobs that are made from the images.
  BLOBNBOX_LIST image_bblobs_;
  // Horizontal line separators.
  TabVector_LIST horizontal_lines_;
  // Image map of photo/noise areas on the page.
  Pix* nontext_map_;
  // Textline projection map.
  TextlineProjection projection_;
  // Sequence of DENORMS that indicate how to get back to the original image
  // coordinate space. The destructor must delete all the DENORMs in the chain.
  DENORM* denorm_;

  // Various debug windows that automatically go away on completion.
  ScrollView* input_blobs_win_;

  // The equation region detector pointer. Note: This pointer is passed in by
  // member function SetEquationDetect, and releasing it is NOT owned by this
  // class.
  EquationDetectBase* equation_detect_;

  // Allow a subsequent instance to reuse the blocks window.
  // Not thread-safe, but multiple threads shouldn't be using windows anyway.
  static ScrollView* blocks_win_;
};

}  // namespace tesseract.

#endif  // TESSERACT_TEXTORD_COLFIND_H__


text:
stackNavigationController is a navigationController with stack animation and swipe gesture supported.

![Screenshot](https://github.com/fsjack/StackNavigationController/raw/master/screenshot.png)

##Installation

- Copy over the `StackNavigationController` folder to your project folder.
- Import `QuartzCore` Library to your project
- `#import "StackNavigationController"`

##Usage
Example project included (StackNavigationControllerDemo)

###Initialization
`SNBaseNavigationController *navigationController = [SNBaseNavigationController navigationWithRootController:self.viewController navigationTransitionStyle:SNBaseNavigationTransitionStyleStack];`

There's two transitionStyle SNBaseNavigationTransitionStyleDefault and SNBaseNavigationTransitionStyleStack,SNBaseNavigationTransitionStyleDefault act exactly the same with NavigationController.

###How to obtain viewController's navigationController
If you use SNBaseNavigationController as your containerViewController it'd be confuse how to obtain viewController's navigationController since it's no longer UINavigationController.But I have fix this problem so you can get obtain SNbaseNavigationController by using `self.navigationController` and
`self.baseNavigationController` also is fine.

##Notes
### NO TabBar supproted yet
### Automatic Reference Counting (ARC) support
StackNavigationController was made with ARC enabled by default.

## Contact
- [GitHub](http://github.com/fsjack)
- [Twitter](http://twitter.com/iamjackiechueng)
- [LinkedIn](http://www.linkedin.com/profile/view?id=91111533)
- [Email](mailto:fsjack@gmail.com)

## License

### MIT License

Copyright (c) 2012 Jackie CHEUNG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.


text:
from copy import deepcopy

import numpy as np

from mushroom_rl.core import Agent
from mushroom_rl.approximators.parametric.torch_approximator import *
from mushroom_rl.approximators.regressor import Regressor
from mushroom_rl.utils.replay_memory import PrioritizedReplayMemory, ReplayMemory
from mushroom_rl.utils.parameters import to_parameter

class AbstractDQN(Agent):
    def __init__(self, mdp_info, policy, approximator, approximator_params,
                 batch_size, target_update_frequency,
                 replay_memory=None, initial_replay_size=500,
                 max_replay_size=5000, fit_params=None, predict_params=None, clip_reward=False):
        """
        Constructor.

        Args:
            approximator (object): the approximator to use to fit the
               Q-function;
            approximator_params (dict): parameters of the approximator to
                build;
            batch_size ([int, Parameter]): the number of samples in a batch;
            target_update_frequency (int): the number of samples collected
                between each update of the target network;
            replay_memory ([ReplayMemory, PrioritizedReplayMemory], None): the
                object of the replay memory to use; if None, a default replay
                memory is created;
            initial_replay_size (int): the number of samples to collect before
                starting the learning;
            max_replay_size (int): the maximum number of samples in the replay
                memory;
            fit_params (dict, None): parameters of the fitting algorithm of the
                approximator;
            predict_params (dict, None): parameters for the prediction with the
                approximator;
            clip_reward (bool, False): whether to clip the reward or not.

        """
        self._fit_params = dict() if fit_params is None else fit_params
        self._predict_params = dict() if predict_params is None else predict_params

        self._batch_size = to_parameter(batch_size)
        self._clip_reward = clip_reward
        self._target_update_frequency = target_update_frequency

        if replay_memory is not None:
            self._replay_memory = replay_memory
            if isinstance(replay_memory, PrioritizedReplayMemory):
                self._fit = self._fit_prioritized
            else:
                self._fit = self._fit_standard
        else:
            self._replay_memory = ReplayMemory(initial_replay_size,
                                               max_replay_size)
            self._fit = self._fit_standard

        self._n_updates = 0

        apprx_params_train = deepcopy(approximator_params)
        apprx_params_target = deepcopy(approximator_params)

        self._initialize_regressors(approximator, apprx_params_train,
                                    apprx_params_target)
        policy.set_q(self.approximator)

        self._add_save_attr(
            _fit_params='pickle',
            _predict_params='pickle',
            _batch_size='mushroom',
            _n_approximators='primitive',
            _clip_reward='primitive',
            _target_update_frequency='primitive',
            _replay_memory='mushroom',
            _n_updates='primitive',
            approximator='mushroom',
            target_approximator='mushroom'
        )

        super().__init__(mdp_info, policy)

    def fit(self, dataset):
        self._fit(dataset)

        self._n_updates += 1
        if self._n_updates % self._target_update_frequency == 0:
            self._update_target()

    def _fit_standard(self, dataset):
        self._replay_memory.add(dataset)
        if self._replay_memory.initialized:
            state, action, reward, next_state, absorbing, _ = \
                self._replay_memory.get(self._batch_size())

            if self._clip_reward:
                reward = np.clip(reward, -1, 1)

            q_next = self._next_q(next_state, absorbing)
            q = reward + self.mdp_info.gamma * q_next

            self.approximator.fit(state, action, q, **self._fit_params)

    def _fit_prioritized(self, dataset):
        self._replay_memory.add(
            dataset, np.ones(len(dataset)) * self._replay_memory.max_priority)
        if self._replay_memory.initialized:
            state, action, reward, next_state, absorbing, _, idxs, is_weight = \
                self._replay_memory.get(self._batch_size())

            if self._clip_reward:
                reward = np.clip(reward, -1, 1)

            q_next = self._next_q(next_state, absorbing)
            q = reward + self.mdp_info.gamma * q_next
            td_error = q - self.approximator.predict(state, action, **self._predict_params)

            self._replay_memory.update(td_error, idxs)

            self.approximator.fit(state, action, q, weights=is_weight,
                                  **self._fit_params)

    def draw_action(self, state):
        action = super().draw_action(np.array(state))

        return action

    def _initialize_regressors(self, approximator, apprx_params_train,
                               apprx_params_target):
        self.approximator = Regressor(approximator, **apprx_params_train)
        self.target_approximator = Regressor(approximator,
                                             **apprx_params_target)
        self._update_target()

    def _update_target(self):
        """
        Update the target network.

        """
        self.target_approximator.set_weights(self.approximator.get_weights())

    def _next_q(self, next_state, absorbing):
        """
        Args:
            next_state (np.ndarray): the states where next action has to be
                evaluated;
            absorbing (np.ndarray): the absorbing flag for the states in
                ``next_state``.

        Returns:
            Maximum action-value for each state in ``next_state``.

        """
        raise NotImplementedError

    def _post_load(self):
        if isinstance(self._replay_memory, PrioritizedReplayMemory):
            self._fit = self._fit_prioritized
        else:
            self._fit = self._fit_standard

        self.policy.set_q(self.approximator)

    def set_logger(self, logger, loss_filename='loss_Q'):
        """
        Setter that can be used to pass a logger to the algorithm

        Args:
            logger (Logger): the logger to be used by the algorithm;
            loss_filename (str, 'loss_Q'): optional string to specify the loss filename.

        """
        self.approximator.set_logger(logger, loss_filename)


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">

  <title>CSS 2.1 Test Suite: font</title>

  <link rel="help" href="http://www.w3.org/TR/CSS21/fonts.html#font-shorthand" title="15.8 Shorthand font property: the 'font' property">
  <link rel="help" href="http://www.w3.org/TR/CSS21/visudet.html#q26" title="10.8.1 Leading and half-leading">

   This text should be 18px serif. There should be a 9px gap between each line.
    dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text dummy
   text dummy text dummy text dummy text dummy text dummy text


text:
FROM alpine:3.7
LABEL Author="Luis Alonzo <wichon@gmail.com>" Description="A Simple apache/php image using alpine Linux for Web Apps"

# Install gnu-libconv required by php5-iconv
RUN apk add --no-cache --repository http://dl-cdn.alpinelinux.org/alpine/edge/testing gnu-libiconv
ENV LD_PRELOAD /usr/lib/preloadable_libiconv.so

# Setup apache and php
RUN apk --update add apache2 php5-apache2 curl \
    php5-json php5-phar php5-openssl php5-mysql php5-curl php5-mcrypt php5-pdo_mysql php5-ctype php5-gd php5-xml php5-dom php5-iconv \
    && rm -f /var/cache/apk/* \
    && mkdir /run/apache2 \
    && mkdir -p /opt/utils

EXPOSE 80

ADD start.sh /opt/utils/

RUN chmod +x /opt/utils/start.sh

ENTRYPOINT ["/opt/utils/start.sh"]


text:
<title>Constants - Using as</title>
<meta http-equiv="Content-Type" content="text/html">
<meta name="description" content="Using as">
<meta name="generator" content="makeinfo 4.7">
<link title="Top" rel="start" href="index.html#Top">
<link rel="up" href="Syntax.html#Syntax" title="Syntax">
<link rel="prev" href="Statements.html#Statements" title="Statements">
<link href="http://www.gnu.org/software/texinfo/" rel="generator-home" title="Texinfo Homepage">

<meta http-equiv="Content-Style-Type" content="text/css">

Previous: Statements,
Up: Syntax

3.6 Constants

A constant is a number, written so that its value is known by
inspection, without knowing any context.  Like this:

     .byte  74, 0112, 092, 0x4A, 0X4a, 'J, '\J # All the same value.
     .ascii "Ring the bell\7"                  # A string constant.
     .octa  0x123456789abcdef0123456789ABCDEF0 # A bignum.
     .float 0f-314159265358979323846264338327\
     95028841971.693993751E-40                 # - pi, a flonum.

Characters:                   Character Constants

Numbers:                      Number Constants


text:
import io
import uuid
import datetime
from werkzeug.http import http_date
from itsdangerous import json as _json
from ._compat import text_type, PY2

class JSONEncoder(_json.JSONEncoder):
    def default(self, o):
        if isinstance(o, datetime.date):
            return http_date(o.timetuple())
        if isinstance(o, uuid.UUID):
            return str(o)
        if hasattr(o, '__html__'):
            return text_type(o.__html__())
        return _json.JSONEncoder.default(self, o)

class JSONDecoder(_json.JSONDecoder):
    pass

def jsonify(__cx, *__args, **__kw):
    app = __cx.app
    rq = __cx.request
    pretty = (app.config['JSONIFY_PRETTYPRINT_REGULAR']
              and not rq.is_xhr)
    # For security reasons only objects are supported toplevel
    indent = None
    separators = (',', ':')
    if pretty:
        indent = 2
        separators = (', ', ': ')
    json = __cx.dumps(dict(*__args, **__kw),
                      indent=indent,
                      separators=separators)
    # add '\n' to end of response
    # see https://github.com/mitsuhiko/flak/pull/1262
    return app.response_class((json, '\n'),
                              mimetype='application/json')

def dump_defaults(app, kw):
    if app:
        kw.setdefault('cls', app.json_encoder)
        if not app.config['JSON_AS_ASCII']:
            kw.setdefault('ensure_ascii', False)
        kw.setdefault('sort_keys', app.config['JSON_SORT_KEYS'])
    else:
        kw.setdefault('sort_keys', True)
        kw.setdefault('cls', JSONEncoder)

def load_defaults(app, kw):
    if app:
        kw.setdefault('cls', app.json_decoder)
    else:
        kw.setdefault('cls', JSONDecoder)

def _dumps(obj, **kw):
    encoding = kw.pop('encoding', None)
    rv = _json.dumps(obj, **kw)
    if encoding is not None and isinstance(rv, text_type):
        rv = rv.encode(encoding)
    return rv

def _dump(obj, fp, **kw):
    encoding = kw.pop('encoding', None)
    if encoding is not None:
        fp = _wrap_writer_for_text(fp, encoding)
    _json.dump(obj, fp, **kw)

def _loads(s, **kw):
    if isinstance(s, bytes):
        s = s.decode(kw.pop('encoding', None) or 'utf-8')
    return _json.loads(s, **kw)

def _load(fp, **kw):
    if not PY2:
        fp = _wrap_reader_for_text(fp, kw.pop('encoding', None) or 'utf-8')
    return _json.load(fp, **kw)

def _wrap_reader_for_text(fp, encoding):
    if isinstance(fp.read(0), bytes):
        fp = io.TextIOWrapper(io.BufferedReader(fp), encoding)
    return fp

def _wrap_writer_for_text(fp, encoding):
    try:
        fp.write('')
    except TypeError:
        fp = io.TextIOWrapper(fp, encoding)
    return fp


text:
package org.eclipse.swt.snippets;

/*
 * Caret example snippet: create a caret
 *
 * For a list of all SWT example snippets see
 * http://www.eclipse.org/swt/snippets/
 */
import org.eclipse.swt.*;
import org.eclipse.swt.widgets.*;

public class Snippet74 {

public static void main (String [] args) {
	Display display = new Display ();
	Shell shell = new Shell (display);
	Caret caret = new Caret (shell, SWT.NONE);
	caret.setBounds (10, 10, 2, 32);
	shell.open ();
	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}
	display.dispose ();
}
}


text:
package publichealthcomplaint.complaintmgr.impl;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import publichealthcomplaint.complaintmgr.spec.req.IPersistenceMechanism;
import publichealthcomplaint.datatypes.IAddressDt;
import publichealthcomplaint.exceptionhandling.impl.ExceptionMessages;
import publichealthcomplaint.exceptionhandling.impl.ObjectAlreadyInsertedException;
import publichealthcomplaint.exceptionhandling.impl.ObjectNotFoundException;
import publichealthcomplaint.exceptionhandling.impl.ObjectNotValidException;
import publichealthcomplaint.exceptionhandling.impl.PersistenceMechanismException;
import publichealthcomplaint.exceptionhandling.impl.RepositoryException;

/**
 * Repositorio responsavel por realizar a persitencia
 * de enderecos. Esse persistencia e realizada em banco
 * de dados relacional utilizando JDBC
 */
class AddressRepositoryRDB{

	private IPersistenceMechanism mp;

	private ResultSet resultSet;

	AddressRepositoryRDB() {

	}

	/**
	 * Metodo para insercao de endereco no repositrorio persistente.
	 * Essa implementacao faz a persistencia atraves de JDBC
	 * conectando com um banco de dados relacional.
	 */
	int insert(IAddressDt end) throws ObjectAlreadyInsertedException, ObjectNotValidException,
		ObjectNotValidException, RepositoryException {

		// teste da validade do objeto a ser inserido
		if (end == null) {
			throw new ObjectNotValidException(ExceptionMessages.EXC_NULO);
		}

		Statement stmt;

		try {

			// Bloco para a recuperacao de um codigo sequencial do
			// banco de dados para ser utilizado como identificador
			// e codigo da tabela de enderecos.
			String consulta = null;
			try {

				//pega id e codigo e seta no objeto primeiro
				consulta = "select * from scbs_endereco";

				stmt = (Statement) mp.getCommunicationChannel();
				resultSet = stmt.executeQuery(consulta);

				int count = 0;
				while (resultSet.next()) {
					count++;
				}
				end.setCode(count + 1);

				count++;

				resultSet.close();
				stmt.close();

			} catch (SQLException e) {
				System.out.println(consulta);
				throw new RepositoryException(ExceptionMessages.EXC_FALHA_BD);
			}
			finally
			{
				mp.releaseCommunicationChannel();
			}

			// Consulta na tabela ao codigo gerado pelo trecho anterior.
			// Caso o codigo ja esteja em uso uma excecao e levantada.
			try {
				stmt = (Statement) mp.getCommunicationChannel();
				String sql = "SELECT * FROM scbs_endereco WHERE codigo = '" + end.getCode() + "'";
				resultSet = stmt.executeQuery(sql);

				if (resultSet.next()) {
					throw new ObjectAlreadyInsertedException(ExceptionMessages.EXC_JA_EXISTE);
				}
				resultSet.close();
				stmt.close();
			} catch (SQLException e) {
				throw new PersistenceMechanismException(ExceptionMessages.EXC_FALHA_BD);
			}
			finally
			{
				mp.releaseCommunicationChannel();
			}

			// Essa ultima etapa da insercao insere de fato os valores
			// recebidos no objeto do parametro com codigo e
			// identificador devidamente alterados
			try {
				String sql = "INSERT INTO scbs_endereco VALUES(";

				//sql += end.getId() + ",";
				sql += "'" + end.getCode() + "',";
				sql += "'" + end.getStreet() + "',";
				sql += "'" + end.getComplement() + "',";
				sql += "'" + end.getZip() + "',";
				sql += "'" + end.getState() + "',";
				sql += "'" + end.getPhone() + "',";
				sql += "'" + end.getCity() + "',";
				sql += "'" + end.getNeighbourhood() + "')";

				stmt = (Statement) this.mp.getCommunicationChannel();
				stmt.executeUpdate(sql);
				stmt.close();

			} catch (SQLException e) {
				throw new RepositoryException(ExceptionMessages.EXC_FALHA_BD);
			}
			finally
			{
				mp.releaseCommunicationChannel();
			}

		} catch (PersistenceMechanismException e) {
			throw new RepositoryException(ExceptionMessages.EXC_FALHA_INCLUSAO);
		}

		// TODO THIS IS WRONG!!!
		return -1;
	}

	/**
	 * Metodo para recuperacao de endereco a partir do codigo.
	 *
	 * @param codigo Codigo identificador do endereco a
	 *				 ser recuperado.
	 * @return endereco montado com os dados recuperados do bd
	 * @exception RepositorioException caso ocorra algum problema
	 *			  relacionado ao acesso aos dados persistentes.
	 * @exception ObjetoInexistenteException caso o endereco
	 *			  nao seja encontrada nos dados persistentes
	 */
	IAddressDt search(int code) throws RepositoryException, ObjectNotFoundException {
		IAddressDt end = null;
		String sql = null;
		try {
			sql = "select * from scbs_endereco where " + " codigo = '" + code + "'";
			System.out.println("AddressRepositoryRDB:search()] sql="+sql);
			Statement stmt = (Statement) this.mp.getCommunicationChannel();

			//System.out.println(sql);
			resultSet = stmt.executeQuery(sql);

			if( resultSet == null )
				System.out.println("AddressRepositoryRDB:search()] resultset is null");
			if (resultSet.next()) {
				//long id = resultSet.getLong("ID");
				code = (new Integer(resultSet.getString("codigo"))).intValue();

				String rua = resultSet.getString("rua");
				String complemento = resultSet.getString("complemento");
				String cep = resultSet.getString("cep");
				String uf = resultSet.getString("uf");
				String fone = resultSet.getString("fone");
				String cidade = resultSet.getString("cidade");
				String bairro = resultSet.getString("bairro");
				end = new Address(rua, complemento, cep, uf, fone, cidade, bairro);
				end.setCode(code);

			} else {
				throw new ObjectNotFoundException(ExceptionMessages.EXC_FALHA_PROCURA);
			}
			resultSet.close();
			stmt.close();

		} catch (SQLException e) {
			throw new RepositoryException(ExceptionMessages.EXC_FALHA_BD);
		}
		finally
		{
			mp.releaseCommunicationChannel();
		}

		return end;
	}

}


text:
<?xml version="1.0" encoding="utf-8"?>
<Catalog>
    <CDataCollectionUnit default="1" id="UnitBaseSCBW">
        <EditorCategories value="DataGroup:Unit,DataFamily:Melee,ObjectType:Unit"/>
        <DataRecord Entry="Actor,##id##"/>
        <DataRecord Entry="Button,##id##"/>
        <DataRecord Entry="Model,##id##"/>
        <DataRecord Entry="Unit,##id##"/>
        <DataRecord Entry="Model,##id##Death"/>
        <DataRecord Entry="Model,##id##DeathLow"/>
        <DataRecord Entry="Model,##id##Portrait"/>
        <DataRecord Entry="Light,##id##Portrait"/>
        <DataRecord Entry="Sound,##id##_Birth"/>
        <DataRecord Entry="Sound,##id##_Ready"/>
        <DataRecord Entry="Sound,##id##_Help"/>
        <DataRecord Entry="Sound,##id##_What"/>
        <DataRecord Entry="Sound,##id##_Yes"/>
        <DataRecord Entry="Sound,##id##_Attack"/>
        <DataRecord Entry="Sound,##id##_Pissed"/>
        <DataRecord Entry="Sound,##id##_Movement"/>
        <DataRecord Entry="Sound,##id##_Turning"/>
        <DataRecord Entry="Sound,##id##_Board"/>
        <DataRecord Entry="Sound,##id##_Click"/>
        <DataRecord Entry="Sound,##id##_ClickError"/>
        <DataRecord Entry="Sound,##id##_Highlight"/>
        <DataRecord Entry="Sound,##id##_Death"/>
        <DataRecord Entry="Sound,##id##_Explode"/>
        <DataRecord Entry="Model,##id##DeathAcid"/>
        <DataRecord Entry="Model,##id##DeathBlast"/>
        <DataRecord Entry="Model,##id##DeathFire"/>
        <DataRecord Entry="Model,##id##DeathRagdoll"/>
        <DataRecord Entry="Model,##id##DeathSilent"/>
        <DataRecord Entry="Model,##id##Placement"/>
    </CDataCollectionUnit>
    <CDataCollectionUnit default="1" id="UnitBaseUnitSCBW" parent="UnitBaseSCBW">
        <EditorCategories value="DataGroup:Unit,DataFamily:Melee,ObjectType:Structure"/>
        <DataRecord Entry="Actor,##id##_Land"/>
        <DataRecord Entry="Sound,##id##_Land"/>
    </CDataCollectionUnit>
    <CDataCollectionUnit default="1" id="UnitBaseBuildingSCBW" parent="UnitBaseSCBW">
        <EditorCategories value="DataGroup:Unit,DataFamily:Melee,ObjectType:Structure"/>
        <DataRecord Entry="Actor,##id##Splat"/>
        <DataRecord Entry="Model,##id##Splat"/>
        <DataRecord Entry="Model,##id##Birth"/>
        <DataRecord Entry="Model,##id##DeathUnderConstruction"/>
        <DataRecord Entry="Model,##id##EmptyDeath"/>
        <DataRecord Entry="Requirement,Have##id##"/>
        <DataRecord Entry="RequirementNode,CountUnit##id##CompleteOnlyTechTreeCheat"/>
    </CDataCollectionUnit>
    <CDataCollectionUnit default="1" id="ProtossUnitSCBW" parent="UnitBaseUnitSCBW">
        <EditorCategories value="Race:Protoss,DataGroup:Unit,DataFamily:Melee,ObjectType:Unit"/>
        <DataRecord Entry="Model,##id##WarpIn"/>
    </CDataCollectionUnit>
    <CDataCollectionUnit default="1" id="ProtossBuildingSCBW" parent="UnitBaseBuildingSCBW">
        <EditorCategories value="Race:Protoss,DataGroup:Unit,DataFamily:Melee,ObjectType:Structure"/>
    </CDataCollectionUnit>
    <CDataCollectionUnit default="1" id="ProtossStargateUnitSCBW" parent="ProtossUnitSCBW">
        <DataRecord Entry="Actor,##id##WarpInStargate"/>
        <DataRecord Entry="Model,##id##WarpInStargate"/>
    </CDataCollectionUnit>
    <CDataCollectionUpgrade default="1" id="ResearchBaseSCBW">
        <EditorCategories value="DataGroup:Research,DataFamily:Melee,ObjectType:Unit"/>
        <DataRecord Entry="Upgrade,##id##"/>
        <DataRecord Entry="Button,##id##"/>
        <DataRecord Entry="Button,##id##Research"/>
        <DataRecord Entry="Requirement,Have##id##"/>
        <DataRecord Entry="Requirement,Learn##id##"/>
        <DataRecord Entry="RequirementNode,CountUpgrade##id##CompleteOnly"/>
        <DataRecord Entry="RequirementNode,CountUpgrade##id##QueuedOrBetter"/>
        <DataRecord Entry="RequirementNode,EqCountUpgrade##id##QueuedOrBetter0"/>
    </CDataCollectionUpgrade>
    <!--
    <CDataCollectionUnit id="ArchonSCBW" parent="ProtossUnitSCBW"/>
    <CDataCollectionUnit id="CorsairSCBW" parent="ProtossStargateUnitSCBW"/>
    <CDataCollectionUnit id="DarkArchonSCBW" parent="ProtossUnitSCBW"/>
-->
    <CDataCollectionUpgrade id="DragoonSCBWSingularityCharge" parent="ResearchBaseSCBW">
        <EditorCategories value="DataGroup:Research,DataFamily:Melee,Race:Protoss,ObjectType:Unit"/>
    </CDataCollectionUpgrade>
    <CDataCollectionUpgrade id="ReaverSCBWIncreasedCapacity" parent="ResearchBaseSCBW">
        <EditorCategories value="DataGroup:Research,DataFamily:Melee,Race:Protoss,ObjectType:Unit"/>
        <DataRecord index="5" Entry="RequirementNode,CountUpgradeDragoonSCBWSingularityChargeCompleteOnly"/>
    </CDataCollectionUpgrade>
    <CDataCollectionUpgrade id="ReaverSCBWScarabDamage" parent="ResearchBaseSCBW">
        <EditorCategories value="DataGroup:Research,DataFamily:Melee,Race:Protoss,ObjectType:Unit"/>
        <DataRecord index="5" Entry="RequirementNode,CountUpgradeDragoonSCBWSingularityChargeCompleteOnly"/>
    </CDataCollectionUpgrade>
    <CDataCollectionUnit id="StargateSCBW" parent="ProtossBuildingSCBW">
        <EditorCategories value=""/>
        <DataRecord index="5" Entry="Model,StargateDeathLow"/>
        <DataRecord index="7" Entry="Light,StargatePortrait"/>
        <DataRecord index="21" Entry="Sound,Stargate_Death"/>
        <DataRecord index="23" Entry="Model,StargateDeathAcid"/>
        <DataRecord index="24" Entry="Model,StargateDeathBlast"/>
        <DataRecord index="25" Entry="Model,StargateDeathFire"/>
        <DataRecord index="26" Entry="Model,StargateDeathRagdoll"/>
        <DataRecord index="27" Entry="Model,StargateDeathSilent"/>
        <DataRecord index="33" Entry="Model,StargateEmptyDeath"/>
    </CDataCollectionUnit>
    <!--
    <CDataCollectionUnit id="HighTemplarSCBW" parent="ProtossUnitSCBW"/>
    <CDataCollectionUnit id="ObserverSCBW" parent="ProtossUnitSCBW"/>
    <CDataCollectionUnit id="ProbeSCBW" parent="ProtossUnitSCBW"/>
    <CDataCollectionUnit id="ReaverSCBW" parent="ProtossUnitSCBW"/>
    <CDataCollectionUnit id="ScoutSCBW" parent="ProtossStargateUnitSCBW"/>
    <CDataCollectionUnit id="ZealotSCBW" parent="ProtossUnitSCBW"/>
-->
    <CDataCollectionUpgrade id="ZealotSCBWLegEnhancements" parent="ResearchBaseSCBW">
        <EditorCategories value="DataGroup:Research,DataFamily:Melee,ObjectType:Unit,Race:Protoss"/>
    </CDataCollectionUpgrade>
</Catalog>


text:
package com.fasterxml.jackson.dataformat.xml.deser;

import java.io.IOException;

import javax.xml.XMLConstants;
import javax.xml.stream.*;

import com.fasterxml.jackson.dataformat.xml.XmlNameProcessor;
import org.codehaus.stax2.XMLStreamLocation2;
import org.codehaus.stax2.XMLStreamReader2;
import org.codehaus.stax2.ri.Stax2ReaderAdapter;

import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.io.ContentReference;

/**
 * Simple helper class used on top of STAX {@link XMLStreamReader} to further
 * abstract out all irrelevant details, and to expose equivalent of flat token
 * stream with no "fluff" tokens (comments, processing instructions, mixed
 * content) all of which is just to simplify
 * actual higher-level conversion to JSON tokens.
 *

 * Beyond initial idea there are also couple of other detours like ability
 * to "replay" some tokens, add virtual wrappers (ironically to support "unwrapped"
 * array values), and to unroll "Objects" into String values in some cases.
 */
public class XmlTokenStream
{
    // // // main token states:

    public final static int XML_START_ELEMENT = 1;
    public final static int XML_END_ELEMENT = 2;
    public final static int XML_ATTRIBUTE_NAME = 3;
    public final static int XML_ATTRIBUTE_VALUE = 4;
    public final static int XML_TEXT = 5;

    // New in 2.12: needed to "re-process" previously encountered START_ELEMENT,
    // with possible leading text
    // public final static int XML_DELAYED_START_ELEMENT = 6;

    // 2.12 also exposes "root scalars" as-is, instead of wrapping as Objects; this
    // needs some more state management too
    public final static int XML_ROOT_TEXT = 7;

    public final static int XML_END = 8;

    // // // token replay states

    private final static int REPLAY_START_DUP = 1;
    private final static int REPLAY_END = 2;
    private final static int REPLAY_START_DELAYED = 3;

    // Some helpful XML Constants

    private final static String XSI_NAMESPACE = XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;

    /*
    /**********************************************************************
    /* Configuration
    /**********************************************************************
     */

    protected final XMLStreamReader2 _xmlReader;

    // @since 2.13 (was untyped before)
    protected final ContentReference _sourceReference;

    /**
     * Bit flag composed of bits that indicate which
     * {@link FromXmlParser.Feature}s
     * are enabled.
     */
    protected int _formatFeatures;

    protected boolean _cfgProcessXsiNil;

    protected XmlNameProcessor _nameProcessor;

    /*
    /**********************************************************************
    /* Parsing state
    /**********************************************************************
     */

    protected int _currentState;

    protected int _attributeCount;

    /**
     * Marker used to indicate presence of `xsi:nil="true"' in current START_ELEMENT.
     *
     * @since 2.10
     */
    protected boolean _xsiNilFound;

    /**
     * Flag set true if current event is {@code XML_TEXT} and there is START_ELEMENT
     *
     * @since 2.12
     */
    protected boolean _startElementAfterText;

    /**
     * Index of the next attribute of the current START_ELEMENT
     * to return (as field name and value pair), if any; -1
     * when no attributes to return
     */
    protected int _nextAttributeIndex;

    protected String _localName;

    protected String _namespaceURI;

    /**
     * Current text value for TEXT_VALUE returned
     */
    protected String _textValue;

    /**
     * Marker flag set if caller wants to "push back" current token so
     * that next call to {@link #next()} should simply be given what was
     * already read.
     *
     * @since 2.12
     */
    protected boolean _repeatCurrentToken;

    /**
     * Reusable internal value object
     *
     * @since 2.14
     */
    protected XmlNameProcessor.XmlName _nameToDecode = new XmlNameProcessor.XmlName();

    /*
    /**********************************************************************
    /* State for handling virtual wrapping
    /**********************************************************************
     */

    /**
     * Flag used to indicate that given element should be "replayed".
     */
    protected int _repeatElement;

    /**
     * Wrapping state, if any active (null if none)
     */
    protected ElementWrapper _currentWrapper;

    /**
     * In cases where we need to 'inject' a virtual END_ELEMENT, we may also
     * need to restore START_ELEMENT afterwards; if so, this is where names
     * are held.
     */
    protected String _nextLocalName;
    protected String _nextNamespaceURI;

    /*
    /**********************************************************************
    /* Life-cycle
    /**********************************************************************
     */

    public XmlTokenStream(XMLStreamReader xmlReader, ContentReference sourceRef,
            int formatFeatures, XmlNameProcessor nameProcessor)
    {
        _sourceReference = sourceRef;
        _formatFeatures = formatFeatures;
        _cfgProcessXsiNil = FromXmlParser.Feature.PROCESS_XSI_NIL.enabledIn(_formatFeatures);
        _xmlReader = Stax2ReaderAdapter.wrapIfNecessary(xmlReader);
        _nameProcessor = nameProcessor;
    }

    /**
     * Second part of initialization, to be called immediately after construction
     *
     * @since 2.12
     */
    public int initialize() throws XMLStreamException
    {
        // Let's ensure we point to START_ELEMENT...
        if (_xmlReader.getEventType() != XMLStreamConstants.START_ELEMENT) {
            throw new IllegalArgumentException("Invalid XMLStreamReader passed: should be pointing to START_ELEMENT ("
                    +XMLStreamConstants.START_ELEMENT+"), instead got "+_xmlReader.getEventType());
        }
        _checkXsiAttributes(); // sets _attributeCount, _nextAttributeIndex
        _decodeElementName(_xmlReader.getNamespaceURI(), _xmlReader.getLocalName());

        // 02-Jul-2020, tatu: Two choices: if child elements OR attributes, expose
        //    as Object value; otherwise expose as Text
        // 06-Sep-2022, tatu: Actually expose as Object in almost every situation
        //    as of 2.14: otherwise we have lots of issues with empty POJOs,
        //    Lists, Maps
        if (_xmlReader.isEmptyElement()
            && FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL.enabledIn(_formatFeatures)
            && !_xsiNilFound
            && _attributeCount < 1) {
            // 06-Sep-2022, tatu: In fact the only special case of null conversion
            //    of the root empty element
            _textValue = null;
            _startElementAfterText = false;
            return (_currentState = XML_ROOT_TEXT);
        }
        return (_currentState = XML_START_ELEMENT);

        // 06-Sep-2022, tatu: This code was used in 2.12, 2.13, may be
        //   removed after 2.14 if/when no longer needed

        // copied from START_ELEMENT section of _next():
        /*
        final String text = _collectUntilTag();
        if (text == null) {
            // 30-Nov-2020, tatu: [dataformat-xml#435], this is tricky
            //   situation since we got coerced `null`... but at least for
            //   now will have to report as "root String" (... with null contents)
            _textValue = null;
            _startElementAfterText = false;
            return (_currentState = XML_ROOT_TEXT);
        }

        final boolean startElementNext = _xmlReader.getEventType() == XMLStreamReader.START_ELEMENT;
        // If we have no/all-whitespace text followed by START_ELEMENT, ignore text
        if (startElementNext) {
            if (_allWs(text)) {
                _textValue = null;
                return (_currentState = XML_DELAYED_START_ELEMENT);
            }
            _textValue = text;
            return (_currentState = XML_DELAYED_START_ELEMENT);
        }
        _startElementAfterText = false;
        _textValue = text;
        return (_currentState = XML_ROOT_TEXT);
        */
    }

    public XMLStreamReader2 getXmlReader() {
        return _xmlReader;
    }

    /**
     * @since 2.9
     */
    protected void setFormatFeatures(int f) {
        _formatFeatures = f;
        _cfgProcessXsiNil = FromXmlParser.Feature.PROCESS_XSI_NIL.enabledIn(f);
    }

    /*
    /**********************************************************************
    /* Public API
    /**********************************************************************
     */

    // DEBUGGING
    /*
    public int next() throws XMLStreamException
    {
        int n = next0();
        switch (n) {
        case XML_START_ELEMENT:
            System.out.printf(" XmlTokenStream.next(): XML_START_ELEMENT '%s' %s\n", _localName, _loc());
            break;
        case XML_DELAYED_START_ELEMENT:
            System.out.printf(" XmlTokenStream.next(): XML_DELAYED_START_ELEMENT '%s' %s\n", _localName, _loc());
            break;
        case XML_END_ELEMENT:
            // 24-May-2020, tatu: no name available for end element so do not print
            System.out.printf(" XmlTokenStream.next(): XML_END_ELEMENT %s\n", _loc());
            break;
        case XML_ATTRIBUTE_NAME:
            System.out.printf(" XmlTokenStream.next(): XML_ATTRIBUTE_NAME '%s' %s\n", _localName, _loc());
            break;
        case XML_ATTRIBUTE_VALUE:
            System.out.printf(" XmlTokenStream.next(): XML_ATTRIBUTE_VALUE '%s' %s\n", _textValue, _loc());
            break;
        case XML_TEXT:
            System.out.printf(" XmlTokenStream.next(): XML_TEXT '%s' %s\n", _textValue, _loc());
            break;
        case XML_END:
            System.out.printf(" XmlTokenStream.next(): XML_END %s\n", _loc());
            break;
        default:
            throw new IllegalStateException();
        }
        return n;
    }

    private String _loc() {
        JsonLocation loc = getCurrentLocation();
        return String.format("[line: %d, column: %d]", loc.getLineNr(), loc.getColumnNr());
    }
    */

//    public int next0() throws XMLStreamException
    public int next() throws XMLStreamException
    {
        if (_repeatCurrentToken) {
            _repeatCurrentToken = false;
            return _currentState;
        }
        if (_repeatElement != 0) {
            return (_currentState = _handleRepeatElement());
        }
        return _next();
    }

    public void skipEndElement() throws IOException, XMLStreamException
    {
        int type = next();
        if (type != XML_END_ELEMENT) {
            throw new IOException(String.format(
                    "Internal error: Expected END_ELEMENT, got event of type %s",
                    _stateDesc(type)));
        }
    }

    public int getCurrentToken() { return _currentState; }

    public String getText() { return _textValue; }

    /**
     * Accessor for local name of current named event (that is,
     * {@code XML_START_ELEMENT} or {@code XML_ATTRIBUTE_NAME}).
     *

     * NOTE: name NOT accessible on {@code XML_END_ELEMENT}
     */
    public String getLocalName() { return _localName; }

    public String getNamespaceURI() { return _namespaceURI; }

    public boolean hasXsiNil() {
        return _xsiNilFound;
    }

    /*// not used as of 2.10
    public boolean hasAttributes() {
        return (_currentState == XML_START_ELEMENT) && (_attributeCount > 0);
    }
    */

    public void closeCompletely() throws XMLStreamException {
        _xmlReader.closeCompletely();
    }

    public void close() throws XMLStreamException {
        _xmlReader.close();
    }

    public JsonLocation getCurrentLocation() {
        return _extractLocation(_xmlReader.getLocationInfo().getCurrentLocation());
    }

    public JsonLocation getTokenLocation() {
        return _extractLocation(_xmlReader.getLocationInfo().getStartLocation());
    }

    /*
    /**********************************************************************
    /* Internal API: more esoteric methods
    /**********************************************************************
     */

    /**
     * Method used to add virtual wrapping, which just duplicates START_ELEMENT
     * stream points to, and its matching closing element.
     */
    protected void repeatStartElement()
    {
//System.out.println(" XmlTokenStream.repeatStartElement() for <"+_localName+">, _currentWrapper was: "+_currentWrapper);
        // sanity check: can only be used when just returned START_ELEMENT:
        if (_currentState != XML_START_ELEMENT) {
            // 14-May-2020, tatu: Looks like we DO end up here with empty Lists; if so,
            //    should NOT actually wrap.
            if (_currentState == XML_END_ELEMENT) {
                return;
            }
            throw new IllegalStateException("Current state not XML_START_ELEMENT but "+_currentStateDesc());
        }
        // Important: add wrapper, to keep track...
        if (_currentWrapper == null) {
            _currentWrapper = ElementWrapper.matchingWrapper(null, _localName, _namespaceURI);
        } else {
            _currentWrapper = ElementWrapper.matchingWrapper(_currentWrapper.getParent(), _localName, _namespaceURI);
        }
//System.out.println(" repeatStartElement for "+_localName+", _currentWrapper now: "+_currentWrapper);
        _repeatElement = REPLAY_START_DUP;
    }

    /**
     * Method that can be called to ask stream to literally just return current token
     * with the next call to {@link #next()}, without more work.
     *
     * @since 2.12
     */
    protected void pushbackCurrentToken()
    {
        _repeatCurrentToken = true;
    }

    /**
     * Method called to skip any attributes current START_ELEMENT may have,
     * so that they are not returned as token.
     *
     * @since 2.1
     */
    protected void skipAttributes()
    {
//System.out.println(" XmlTokenStream.skipAttributes(), state: "+_currentStateDesc());
        switch (_currentState) {
        case XML_ATTRIBUTE_NAME:
            _attributeCount = 0;
            _currentState = XML_START_ELEMENT;
            break;
        case XML_START_ELEMENT:
            // 06-Jan-2012, tatu: As per [#47] it looks like we should NOT do anything
            //   in this particular case, because it occurs when original element had
            //   no attributes and we now point to the first child element.
//              _attributeCount = 0;
            break;
        case XML_TEXT:
            break; // nothing to do... is it even legal?

            /*
        case XML_DELAYED_START_ELEMENT:
            // 03-Jul-2020, tatu: and here nothing to do either... ?
            break;
            */
        default:
            throw new IllegalStateException(
"Current state not XML_START_ELEMENT or XML_ATTRIBUTE_NAME but "+_currentStateDesc());
        }
    }

    /*
    /**********************************************************************
    /* Internal methods, parsing
    /**********************************************************************
     */

    private final int _next() throws XMLStreamException
    {
//System.out.println(" XmlTokenStream._next(), state: "+_currentStateDesc());
        switch (_currentState) {
        case XML_ATTRIBUTE_VALUE:
            ++_nextAttributeIndex;
            // fall through
        case XML_START_ELEMENT: // attributes to return?
            // 06-Sep-2019, tatu: `xsi:nil` to induce "real" null value?
            if (_xsiNilFound) {
                _xsiNilFound = false;
                // 08-Jul-2021, tatu: as per [dataformat-xml#467] just skip anything
                //   element might have, no need to ensure it was empty
                _xmlReader.skipElement();
                return _handleEndElement();
            }
            if (_nextAttributeIndex < _attributeCount) {
//System.out.println(" XmlTokenStream._next(): Got attr(s)!");
                _decodeAttributeName(_xmlReader.getAttributeNamespace(_nextAttributeIndex),
                        _xmlReader.getAttributeLocalName(_nextAttributeIndex));
                _textValue = _xmlReader.getAttributeValue(_nextAttributeIndex);
                return (_currentState = XML_ATTRIBUTE_NAME);
            }
            // otherwise need to find START/END_ELEMENT or text
            String text = _collectUntilTag();
//System.out.println(" XmlTokenStream._next(): _collectUntilTag -> '"+text+"'");
            final boolean startElementNext = _xmlReader.getEventType() == XMLStreamReader.START_ELEMENT;
//System.out.println(" XmlTokenStream._next(): startElementNext? "+startElementNext);
            // If we have no/all-whitespace text followed by START_ELEMENT, ignore text
            if (startElementNext) {
                if (_allWs(text)) {
                    _startElementAfterText = false;
                    return _initStartElement();
                }
                _startElementAfterText = true;
                _textValue = text;

                return (_currentState = XML_TEXT);
            }
            // For END_ELEMENT we will return text, if any
            if (text != null) {
                _startElementAfterText = false;
                _textValue = text;
                return (_currentState = XML_TEXT);
            }
            _startElementAfterText = false;
            return _handleEndElement();

            /*
        case XML_DELAYED_START_ELEMENT: // since 2.12, to support scalar Root Value
            // Two cases: either "simple" with not text
           if (_textValue == null) {
               return _initStartElement();
           }
           // or one where there is first text (to translate into "":<text> key/value entry)
           // then followed by start element
           _startElementAfterText = true;
           return (_currentState = XML_TEXT);
           */

        case XML_ATTRIBUTE_NAME:
            // if we just returned name, will need to just send value next
            return (_currentState = XML_ATTRIBUTE_VALUE);
        case XML_TEXT:
            // mixed text with other elements
            if (_startElementAfterText) {
                _startElementAfterText = false;
                return _initStartElement();
            }
            // text followed by END_ELEMENT
            return _handleEndElement();
        case XML_ROOT_TEXT:
            close();
            return (_currentState = XML_END);
        case XML_END:
            return XML_END;
//            throw new IllegalStateException("No more XML tokens available (end of input)");
        }
        // Ok: must be END_ELEMENT; see what tag we get (or end)
        switch (_skipAndCollectTextUntilTag()) {
        case XMLStreamConstants.END_DOCUMENT:
            close();
            return (_currentState = XML_END);
        case XMLStreamConstants.END_ELEMENT:
            // 24-May-2020, tatu: Need to see if we have "mixed content" to offer
            if (!_allWs(_textValue)) {
                // _textValue already set
                return (_currentState = XML_TEXT);
            }
            return _handleEndElement();
        }
        // 24-May-2020, tatu: Need to see if we have "mixed content" to offer
        if (!_allWs(_textValue)) {
            // _textValue already set
            _startElementAfterText = true;
            return (_currentState = XML_TEXT);
        }

        // START_ELEMENT...
        return _initStartElement();
    }

    /**
     * @return Collected text, if any, EXCEPT that if {@code FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL}
     *    AND empty element, returns {@code null}
     */
    private final String _collectUntilTag() throws XMLStreamException
    {
        // 21-Jun-2017, tatu: Whether exposed as `null` or "" is now configurable...
        if (_xmlReader.isEmptyElement()) {
            _xmlReader.next();
            if (FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL.enabledIn(_formatFeatures)) {
                return null;
            }
            return "";
        }

        CharSequence chars = null;
        while (true) {
            switch (_xmlReader.next()) {
            case XMLStreamConstants.START_ELEMENT:
                return (chars == null) ? "" : chars.toString();

            case XMLStreamConstants.END_ELEMENT:
            case XMLStreamConstants.END_DOCUMENT:
                return (chars == null) ? "" : chars.toString();

            // note: SPACE is ignorable (and seldom seen), not to be included
            case XMLStreamConstants.CHARACTERS:
            case XMLStreamConstants.CDATA:
                // 17-Jul-2017, tatu: as per [dataformat-xml#236], need to try to...
                {
                    String str = _getText(_xmlReader);
                    if (chars == null) {
                        chars = str;
                    } else  {
                        if (chars instanceof String) {
                            chars = new StringBuilder(chars);
                        }
                        ((StringBuilder)chars).append(str);
                    }
                }
                break;
            default:
                // any other type (proc instr, comment etc) is just ignored
            }
        }
    }

    // Called to skip tokens until start/end tag (or end-of-document) found, but
    // also collecting cdata until then, if any found, for possible "mixed content"
    // to report
    //
    // @since 2.12
    private final int _skipAndCollectTextUntilTag() throws XMLStreamException
    {
        CharSequence chars = null;

        while (_xmlReader.hasNext()) {
            int type;
            switch (type = _xmlReader.next()) {
            case XMLStreamConstants.START_ELEMENT:
            case XMLStreamConstants.END_ELEMENT:
            case XMLStreamConstants.END_DOCUMENT:
                _textValue = (chars == null) ? "" : chars.toString();
                return type;
            // note: SPACE is ignorable (and seldom seen), not to be included
            case XMLStreamConstants.CHARACTERS:
            case XMLStreamConstants.CDATA:
                {
                    String str = _getText(_xmlReader);
                    if (chars == null) {
                        chars = str;
                    } else  {
                        if (chars instanceof String) {
                            chars = new StringBuilder(chars);
                        }
                        ((StringBuilder)chars).append(str);
                    }
                }
                break;
            default:
                // any other type (proc instr, comment etc) is just ignored
            }
        }
        throw new IllegalStateException("Expected to find a tag, instead reached end of input");
    }

    private final String _getText(XMLStreamReader2 r) throws XMLStreamException
    {
        try {
            return r.getText();
        } catch (RuntimeException e) {
            Throwable cause = e.getCause();
            if (cause instanceof XMLStreamException) {
                throw (XMLStreamException) cause;
            }
            throw e;
        }
    }

    /*
    /**********************************************************************
    /* Internal methods, other
    /**********************************************************************
     */

    private final int _initStartElement() throws XMLStreamException
    {
        final String ns = _xmlReader.getNamespaceURI();
        final String localName = _xmlReader.getLocalName();

        _checkXsiAttributes();

        // Support for virtual wrapping: in wrapping, may either create a new
        // wrapper scope (if in sub-tree, or matches wrapper element itself),
        // or implicitly close existing scope.

        if (_currentWrapper != null) {
            if (_currentWrapper.matchesWrapper(localName, ns)) {
                _currentWrapper = _currentWrapper.intermediateWrapper();
//System.out.println(" _initStartElement(): START_ELEMENT ("+localName+") DOES match ["+_currentWrapper+"]: leave/add intermediate");
            } else {
                // implicit end is more interesting:
//System.out.println(" _initStartElement(): START_ELEMENT ("+localName+") not matching '"+_localName+"'; add extra XML-END-ELEMENT!");
                _localName = _currentWrapper.getWrapperLocalName();
                _namespaceURI = _currentWrapper.getWrapperNamespace();
                _currentWrapper = _currentWrapper.getParent();
                // Important! We also need to restore the START_ELEMENT, so:
                _nextLocalName = localName;
                _nextNamespaceURI = ns;
                _repeatElement = REPLAY_START_DELAYED;
                return (_currentState = XML_END_ELEMENT);
            }
        }
        _decodeElementName(ns, localName);
        return (_currentState = XML_START_ELEMENT);
    }

    /**
     * @since 2.10
     */
    private final void _checkXsiAttributes() {
        int count = _xmlReader.getAttributeCount();
        _attributeCount = count;

        // [dataformat-xml#354]: xsi:nul handling; at first only if first attribute
        if (count >= 1) {
            // [dataformat-xml#468]: may disable xsi:nil processing
            if (_cfgProcessXsiNil
                     && "nil".equals(_xmlReader.getAttributeLocalName(0))) {
                if (XSI_NAMESPACE.equals(_xmlReader.getAttributeNamespace(0))) {
                    // need to skip, regardless of value
                    _nextAttributeIndex = 1;
                    // but only mark as nil marker if enabled
                    _xsiNilFound = "true".equals(_xmlReader.getAttributeValue(0));
                    return;
                }
            }
        }

        _nextAttributeIndex = 0;
        _xsiNilFound = false;
    }

    /**
     * @since 2.14
     */
    protected void _decodeElementName(String namespaceURI, String localName) {
        _nameToDecode.namespace = namespaceURI;
        _nameToDecode.localPart = localName;
        _nameProcessor.decodeName(_nameToDecode);
        _namespaceURI = _nameToDecode.namespace;
        _localName = _nameToDecode.localPart;
    }

    /**
     * @since 2.14
     */
    protected void _decodeAttributeName(String namespaceURI, String localName) {
        _nameToDecode.namespace = namespaceURI;
        _nameToDecode.localPart = localName;
        _nameProcessor.decodeName(_nameToDecode);
        _namespaceURI = _nameToDecode.namespace;
        _localName = _nameToDecode.localPart;
    }

    /**
     * Method called to handle details of repeating "virtual"
     * start/end elements, needed for handling 'unwrapped' lists.
     */
    protected int _handleRepeatElement() throws XMLStreamException
    {
//System.out.println(" XMLTokenStream._handleRepeatElement()");

        int type = _repeatElement;
        _repeatElement = 0;
        if (type == REPLAY_START_DUP) {
//System.out.println(" XMLTokenStream._handleRepeatElement() for START_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
            // important: add the virtual element second time, but not with name to match
            _currentWrapper = _currentWrapper.intermediateWrapper(); // lgtm [java/dereferenced-value-may-be-null]
            return XML_START_ELEMENT;
        }
        if (type == REPLAY_END) {
//System.out.println(" XMLTokenStream._handleRepeatElement() for END_ELEMENT: "+_localName+" ("+_xmlReader.getLocalName()+")");
            _decodeElementName(_xmlReader.getNamespaceURI(), _xmlReader.getLocalName());
            if (_currentWrapper != null) {
                _currentWrapper = _currentWrapper.getParent();
            }
            return XML_END_ELEMENT;
        }
        if (type == REPLAY_START_DELAYED) {
            if (_currentWrapper != null) {
                _currentWrapper = _currentWrapper.intermediateWrapper();
            }
            _decodeElementName(_nextNamespaceURI, _nextLocalName);
            _nextLocalName = null;
            _nextNamespaceURI = null;

//System.out.println(" XMLTokenStream._handleRepeatElement() for START_DELAYED: "+_localName+" ("+_xmlReader.getLocalName()+")");

            return XML_START_ELEMENT;
        }
        throw new IllegalStateException("Unrecognized type to repeat: "+type);
    }

    private final int _handleEndElement()
    {
//System.out.println(" XMLTokenStream._handleEndElement()");
        if (_currentWrapper != null) {
            ElementWrapper w = _currentWrapper;
            // important: if we close the scope, must duplicate END_ELEMENT as well
            if (w.isMatching()) {
                _repeatElement = REPLAY_END;
                // 11-Sep-2022, tatu: I _think_ these are already properly decoded
                _localName = w.getWrapperLocalName();
                _namespaceURI = w.getWrapperNamespace();
                _currentWrapper = _currentWrapper.getParent();
//System.out.println(" XMLTokenStream._handleEndElement(): IMPLICIT requestRepeat of END_ELEMENT '"+_localName);
            } else {
                _currentWrapper = _currentWrapper.getParent();
                // 23-May-2020, tatu: Let's clear _localName since it's value is unlikely
                //    to be correct and we may or may not be able to get real one (for
                //    END_ELEMENT could) -- FromXmlParser does NOT use this info
                _localName = "";
                _namespaceURI = "";

            }
        } else {
            // Not (necessarily) known, as per above, so:
            _localName = "";
            _namespaceURI = "";
        }
        return (_currentState = XML_END_ELEMENT);
    }

    private JsonLocation _extractLocation(XMLStreamLocation2 location)
    {
        if (location == null) { // just for impls that might pass null...
            return new JsonLocation(_sourceReference, -1, -1, -1);
        }
        return new JsonLocation(_sourceReference,
                location.getCharacterOffset(),
                location.getLineNumber(),
                location.getColumnNumber());
    }

    protected static boolean _allWs(String str)
    {
        final int len = (str == null) ? 0 : str.length();
        if (len > 0) {
            for (int i = 0; i < len; ++i) {
                if (str.charAt(i) > ' ') {
                    return false;
                }
            }
        }
        return true;
    }

    protected String _currentStateDesc() {
        return _stateDesc(_currentState);
    }

    protected String _stateDesc(int state) {
        switch (state) {
        case XML_START_ELEMENT:
            return "XML_START_ELEMENT";
        case XML_END_ELEMENT:
            return "XML_END_ELEMENT";
        case XML_ATTRIBUTE_NAME:
            return "XML_ATTRIBUTE_NAME";
        case XML_ATTRIBUTE_VALUE:
            return "XML_ATTRIBUTE_VALUE";
        case XML_TEXT:
            return "XML_TEXT";
        // case XML_DELAYED_START_ELEMENT:
        //    return "XML_START_ELEMENT_DELAYED";
        case XML_ROOT_TEXT:
            return "XML_ROOT_TEXT";
        case XML_END:
            return "XML_END";
        }
        return "N/A ("+_currentState+")";
    }

    // for DEBUGGING
    /*
    @Override
    public String toString()
    {
        return String.format("(Token stream: state=%s attr=%s nextAttr=%s"
                +" name=%s text=%s repeat?=%s wrapper=[%s] repeatElement=%s nextName=%s)",
                _currentState, _attributeCount, _nextAttributeIndex,
                _localName, _textValue, _repeatElement, _currentWrapper, _repeatElement, _nextLocalName);
    }
    */
}


text:
An API for interacting with the MSP430 microcontroller family with [Atom][].
`atom-msp430` wraps common interactions with the 430 in Atom's type-safe and beautiful [Haskell][] DSL.
For a quick demonstration, have a read of [ledblink.lhs][].
More examples will come soon!
To see the current status and goals, have a look at the [roadmap][].

 [Atom]: https://github.com/tomahawkins/atom
 [Haskell]: http://www.haskell.org/
 [ledblink.lhs]: Language/Atom/MSP430/Examples/ledblink.lhs
 [roadmap]: https://github.com/eightyeight/atom-msp430/wiki/Roadmap

## How?

Make sure you have the [Haskell Platform][] installed.

 [Haskell Platform]: http://www.haskell.org/platform

### Using Cabal

```
cabal install atom-msp430
```

### Using git

```
git clone git@github.com:eightyeight/atom-msp430
cd atom-msp430
cabal install
```

## Why?

 1. Because Atom is cool, and Haskell is a great macro language.
 2. Because type-safety can mean more efficient learning as well as safer code.
 3. Because I'm sick of seeing code like this:

```c
void initUART(void) {
    P1SEL = BIT1 + BIT2;        // P1.1 = RXD, P1.2=TXD
    P1SEL2 = BIT1 + BIT2;       // P1.1 = RXD, P1.2=TXD

    UCA0CTL1 |= UCSSEL_1;       // CLK = ACLK
    UCA0BR0 = 0x03;             // 32kHz/9600 = 3.41
    UCA0BR1 = 0x00;
    UCA0MCTL = UCBRS1 + UCBRS0; // Modulation UCBRSx = 3
    UCA0CTL1 &= ~UCSWRST;       // **Initialize USCI state machine**
    IE2 |= UCA0RXIE;            // Enable USCI_A0 RX interrupt
}
```

(Example by oPossum via [msp430launchpad.com][] with no malice intended.
Those guys taught me everything I know about the 430!)

 [msp430launchpad.com]: http://www.msp430launchpad.com/2012/06/using-printf.html


text:
<?php
/**
 * Generated PHP model
 * @author David Spreekmeester | grrr.nl
 * @package Garp
 * @subpackage Spawn
 */
interface Garp_Spawn_Php_Model_Protocol {
	public function render();

	public function getPath();

	public function isOverwriteEnabled();
}