Tuesday, January 19, 2010

ctype










Class Name ctype

Header File <locale>

Classification abstract data type



Class Relationship Diagram



Class Description

Member Classes


locale::id

Methods




explicit ctype(size_t refs = 0);


~ctype();


virtual bool do_is(mask m, charT c) const;


virtual const charT* do_is(const charT* low, const charT* high,
mask* vec) const;


virtual const charT* do_scan_is(mask m, const charT* low,
const charT* high) const;


virtual const charT* do_scan_not(mask m, const charT* low,
const charT* high) const;


virtual char do_narrow(charT, char dfault) const;


virtual const charT* do_narrow(const charT* low, const charT* high,
char dfault, char* dest) const;


virtual charT do_tolower(charT c) const;


virtual const charT* do_tolower(charT* low, const charT* high) const;


virtual charT do_toupper(charT c) const;


virtual const charT* do_toupper(charT* low, const charT* high) const;


virtual charT do_widen(char) const;


virtual const char* do_widen(const char* low, const char* high,
charT* dest) const;


bool is(mask m, charT c) const;


const charT* is(const charT* low, const charT* high, mask* vec) const;


char narrow(charT c, char dfault) const;


const charT* narrow(const charT* low, const charT*, char dfault,
char* to) const;


const charT* scan_is(mask m, const charT* low, const charT* high) const;


const charT* scan_not(mask m, const charT* low, const charT* high) const;


charT tolower(charT c) const;


const charT* tolower(charT* low, const charT* high) const;


charT toupper(charT) const;


const charT* toupper(charT* low, const charT* high) const;


charT widen(char c) const;


const char* widen(const char* low, const char* high, charT* to) const;




Class Description



The ctype template class describes a class used to provide character classifications
and simple conversions.




locale::id



locale::id is a class used to provide an identification of a locale facet interfaces used as
an index for lookup and to encapsulate initialization.







Method ctype()

Access Public

Classification Constructor

Syntax explicit ctype(size_t refs = 0);

Parmeters refs, if the refs argument = 0 then the destruction
of the object is delegated to the locale or locales
which contain it. If refs = 1 then the object must
be explicitly deleted. The locale will not delete it.
The object can then be maintained across the lifetime
of multiple locales.

Returns None



Description



This constructor constructs a ctype facet object.







Method ctype()

Access Protected

Classification Destructor

Syntax ~ctype();

Parmeters None

Returns None



Description



The destructor destroys a ctype facet object.







Method do_is()

Access Protected

Classification Accessor

Syntax virtual bool do_is(mask m, charT c) const;

Parameters m is one of the mask available from the ctype_base.

c is the character to be classified.

Return This method returns true if the character matches the
classification indicated by the mask.



Description



The do_is() method classifies a character. The method determines if the character
matches the classification indicated by the mask argument m. It returns
true if the character matches the classification indicated by the mask.







Method do_is()

Access Protected

Classification Accessor

Syntax virtual const charT* do_is(const charT* low,
const charT* high,
mask* vec) const;

Parameters low is the beginning of a sequence of characters.

high is the end of a sequence of characters.

vec is a vector of masks.

Return This method returns the high argument.



Description



The do_is() method classifies a sequence of characters. The method fills vec with
every mask from the ctype_base and applies it to the sequence of characters in the
range [low, high).







Method do_scan_is()

Access Protected

Classification Accessor

Syntax virtual const charT* do_scan_is(mask m,
const charT* low,
const charT* high) const;

Parameters m is one of the mask available from the ctype_base.


low is the beginning of a sequence of characters.

high is the end of a sequence of characters.


Returns This method returns the first character in the
range that matches the classification indicated
by the mask m.



Description



The do_scan_is() method locates a character in the range [low, high) that
conforms to the classification indicated by the mask argument m.
This method returns the first character in the range that matches the
classification indicated by the mask m. If the character is not in
the range high is returned.








Method do_scan_not()

Access Protected

Classification Accessor

Syntax virtual const charT* do_scan_not(mask m,
const charT* low,
const charT* high) const;

Parameters m is one of the mask available from the ctype_base.


low is the beginning of a sequence of characters.

high is the end of a sequence of characters.


Returns This method returns the first character in the
range that does not match the classification
indicated by the mask m.



Description



The do_scan_is() method locates a character in the range [low, high) that
does not conform to the classification indicated by the mask argument m.
This method returns the first character in the range that does not match the
classification indicated by the mask m. If the character is not in
the range high is returned.








Method do_narrow()

Access Protected

Classification Modifier

Syntax virtual char do_narrow(charT c, char dfault) const;

Parameters c is the character to be transformed.

dfault is character that is returned if no
transformation takes places.

Returns This method returns the transformed value or
dfault if no transformation takes place.



Description



The do_narrow() method applies the simplest transformation from a charT value
to the corresponding char value if it exist. The method returns the transformed
value or returns the dfault argument if no transformation is possible.







Method do_narrow()

Access Protected

Classification Modifier

Syntax virtual const charT* do_narrow(const charT* low,
const charT* high,
char dfault,
char* dest) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.

dfault is used as a default transformation.

dest is the destination of the results.

Returns This method returns high.




Description



The do_narrow() method applies the simplest transformation from a sequence of charT
values to the corresponding char values if they exist. If no simple transformation
is possible then dfault is used. The method returns the transformed
values in dest argument.







Method do_tolower()

Access Protected

Classification Modifier

Syntax virtual charT do_tolower(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the converted character.



Description



The do_tolower() method converts the character argument c to
lower case. The method returns the converted character. If no conversion is
possible the argument is returned.







Method do_tolower()

Access Protected

Classification Modifier

Syntax virtual charT do_tolower(charT* low,
const charT* high) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.


Returns This method returns high.



Description



The do_tolower() method converts each character in the character sequence
[low, high) argument to lower case. Each character in the range is replaced
with the lower case character. The method returns high.







Method do_toupper()

Access Protected

Classification Modifier

Syntax virtual charT do_toupper(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the converted character.



Description



The do_tolower() method converts the character argument c to
upper case. The method returns the converted character. If no conversion is
possible the argument is returned.







Method do_toupper()

Access Protected

Classification Modifier

Syntax virtual charT do_toupper(charT* low,
const charT* high) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.


Returns This method returns high.



Description



The do_tolower() method converts each character in the character sequence
[low, high) argument to upper case. Each character in the range is replaced
with the upper case character. The method returns high.







Method do_widen()

Access Protected

Classification Modifier

Syntax virtual charT do_widen(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the transformed character.



Description



The do_tolower() method applies the simplest transformation from a char value
to the corresponding charT value.







Method do_widen()

Access Protected

Classification Modifier

Syntax virtual const charT* do_widen(const char* low,
const char* high,
charT* dest) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.

dest is the destination of the results.

Returns This method returns high.




Description



The do_narrow() method applies the simplest transformation from a sequence of char
values to the corresponding charT values if they exist. The method returns the
transformed values in dest argument. The method returns high.







Method is()

Access Public

Classification Accessor

Syntax bool is(mask m, charT c) const;

Parameters m is one of the mask available from the ctype_base.

c is the character to be classified.

Return This method returns true if the character matches the
classification indicated by the mask.



Description



The do_is() method returns do_is(m, c).







Method is()

Access Public

Classification Accessor

Syntax const charT* is(const charT* low,
const charT* high,
mask* vec) const;

Parameters low is the beginning of a sequence of characters.

high is the end of a sequence of characters.

vec is a vector of masks.

Return This method returns the high argument.



Description



The do_is() method returns do_is(low, high, vec).







Method scan_is()

Access Public

Classification Accessor

Syntax const charT* scan_is(mask m,
const charT* low,
const charT* high) const;

Parameters m is one of the mask available from the ctype_base.


low is the beginning of a sequence of characters.

high is the end of a sequence of characters.


Returns This method returns the first character in the
range that matches the classification indicated
by the mask m.



Description



The scan_is() method returns do_scan_is(m, low, high).







Method scan_not()

Access Public

Classification Accessor

Syntax const charT* scan_not(mask m,
const charT* low,
const charT* high) const;

Parameters m is one of the mask available from the ctype_base.


low is the beginning of a sequence of characters.

high is the end of a sequence of characters.


Returns This method returns the first character in the
range that does not match the classification
indicated by the mask m.



Description



The scan_not() method returns scan_not(m, low, high).







Method narrow()

Access Public

Classification Modifier

Syntax char narrow(charT c, char dfault) const;

Parameters c is the character to be transformed.

dfault is character that is returned if no
transformation takes places.

Returns This method returns the transformed value or
dfault if no transformation takes place.



Description



The narrow() method returns do_narrow(c, dfault).







Method narrow()

Access Public

Classification Modifier

Syntax const charT* narrow(const charT* low,
const charT* high,
char dfault,
char* to) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.

dfault is used as a default transformation.

to is the destination of the results.

Returns This method returns high.




Description



The narrow() method returns do_narrow(low, high, dfault,to).







Method tolower()

Access Public

Classification Modifier

Syntax charT tolower(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the converted character.



Description



The tolower() method returns do_tolower(c).







Method tolower()

Access Public

Classification Modifier

Syntax charT tolower(charT* low,
const charT* high) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.


Returns This method returns high.



Description



The tolower() method returns do_tolower(low, high).







Method toupper()

Access Public

Classification Modifier

Syntax charT toupper(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the converted character.



Description



The toupper() method returns do_toupper(c).







Method toupper()

Access Public

Classification Modifier

Syntax charT do_toupper(charT* low,
const charT* high) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.


Returns This method returns high.



Description



The toupper() method returns do_toupper(low, high).







Method widen()

Access Public

Classification Modifier

Syntax charT widen(charT c) const;

Parameters c is the character to be converted.

Returns This method returns the transformed character.



Description



The widen() method returns do_widen(c).







Method widen()

Access Public

Classification Modifier

Syntax const charT* widen(const char* low,
const char* high,
charT* to) const;

Parameters low is the beginning of a sequence of
characters.

high is the end of a sequence of
characters.

to is the destination of the results.

Returns This method returns high.




Description



The widen() method returns do_widen(low, high, to).





The Class Relationship Diagram for ctype





8.6 Enhancements in Oracle Database 10g











 < Day Day Up > 







8.6 Enhancements in Oracle Database 10g





Oracle

Database

10g introduces some new features for

hierarchical queries. The new features include the CONNECT_BY_ROOT

operator, the new CONNECT_BY_ISCYCLE and CONNECT_BY_ISLEAF

pseudocolumns, and the NOCYCLE keyword. We will discuss each of these

enhancements in the following sections.







8.6.1 Getting Data from the Root Row





Remember how you can use the PRIOR operator to retrieve a value from

a node's parent row? You can now use the







CONNECT_BY_ROOT operator to retrieve

a value from a node's root. For example:





SELECT lname "Employee", CONNECT_BY_ROOT lname "Top Manager"

FROM employee

START WITH manager_emp_id = 7839

CONNECT BY PRIOR emp_id = manager_emp_id;



Employee Top Manager

-------------------- ------------

JONES JONES

SCOTT JONES

ADAMS JONES

FORD JONES

SMITH JONES

BLAKE BLAKE

ALLEN BLAKE

WARD BLAKE

MARTIN BLAKE

TURNER BLAKE

JAMES BLAKE

CLARK CLARK

MILLER CLARK







In this example, the hierarchy is built by starting with the rows

that meet the condition manager_emp_id = 7839.

This means that anyone whose manager is 7839 will be considered a

root for this query. Those employees will be listed in the result set

of the query along with the name of the top-most manager in their

tree. The CONNECT_BY_ROOT operator returns that top-most manager name

by accessing the root row for each row returned by the query.









8.6.2 Ignoring Cycles





Cycles are not



allowed in

a true tree structure. But life is not perfect, and someday

you're bound to encounter hierarchical data

containing cycles in which a node's child is also

its parent. Such cycles are usually not good, need to be fixed, but

can be frustratingly difficult to identify. You can try to find

cycles by issuing a START WITH . . . CONNECT BY query, but such a

query will report an error if there is a cycle (also known as a loop)

in the data. In Oracle Database 10g, all this

changes.





To allow the START WITH . . . CONNECT BY construct

to work properly even if cycles are present in the data, Oracle

Database 10g provides the new NOCYCLE keyword.

If there are cycles in your data, you can use the



NOCYCLE

keyword in the CONNECT BY clause, and you will not get an error when

hierarchically querying that data.





The test data we have in the employee table

doesn't have a cycle. To test the NOCYCLE feature,

you can introduce a cycle into the existing

employee data by updating the

manager_emp_id column of the top-most employee

(KING with emp_id=7839) with the

manager_emp_id of one of the lowest level

employees (MARTIN with emp_id =

7654):





UPDATE employee

SET manager_emp_id

= 7654

WHERE manager_emp_id IS NULL;







Now, if you perform the following hierarchical query, you will get an

ORA-01436 error:





SELECT LEVEL, LPAD('  ',2*(LEVEL - 1)) || lname "EMPLOYEE", 

emp_id, manager_emp_id

FROM employee

START WITH emp_id = 7839

CONNECT BY PRIOR emp_id = manager_emp_id;



LEVEL EMPLOYEE EMP_ID MANAGER_EMP_ID

---------- -------------------- ---------- --------------

1 KING 7839 7654

2 JONES 7566 7839

3 SCOTT 7788 7566

4 ADAMS 7876 7788

3 FORD 7902 7566

4 SMITH 7369 7902

2 BLAKE 7698 7839

3 ALLEN 7499 7698

3 WARD 7521 7698

3 MARTIN 7654 7698

4 KING 7839 7654

5 JONES 7566 7839

6 SCOTT 7788 7566

7 ADAMS 7876 7788

6 FORD 7902 7566

ERROR:

ORA-01436: CONNECT BY loop in user data







15 rows selected.







Other than the error, notice that the whole tree starting with KING

starts repeating under MARTIN. This is erroneous and confusing. Use

the NOCYCLE keyword in the CONNECT BY clause to get rid of the error

message, and to prevent the listing of erroneously cyclic data:





SELECT LEVEL, LPAD('  ',2*(LEVEL - 1)) || lname "EMPLOYEE", 

emp_id, manager_emp_id

FROM employee

START WITH emp_id = 7839

CONNECT BY NOCYCLE PRIOR emp_id = manager_emp_id;



LEVEL EMPLOYEE EMP_ID MANAGER_EMP_ID

---------- -------------------- ---------- --------------

1 KING 7839 7654

2 JONES 7566 7839

3 SCOTT 7788 7566

4 ADAMS 7876 7788

3 FORD 7902 7566

4 SMITH 7369 7902

2 BLAKE 7698 7839

3 ALLEN 7499 7698

3 WARD 7521 7698

3 MARTIN 7654 7698

3 TURNER 7844 7698

3 JAMES 7900 7698

2 CLARK 7782 7839

3 MILLER 7934 7782







This query recognizes that there is a cycle, ignores the cycle (as an

impact of the NOCYCLE keyword), and returns the rows as if there were

no cycles. Having the ability to query data containing cycles, your

next problem is to identify those cycles.







You can use the NOCYCLE keyword regardless of whether you have a

cycle in your data.












8.6.3 Identifying Cycles





It is sometimes difficult

to



identify cycles in hierarchical data. Oracle Database

10g's new pseudocolumn,





CONNECT_BY_ISCYCLE,

can help you identify the cycles in the data easily.

CONNECT_BY_ISCYCLE can be used only in conjunction with the NOCYCLE

keyword in a hierarchical query. The CONNECT_BY_ISCYCLE pseudocolumn

returns 1 if the current row has a child that is also its ancestor;

otherwise, it returns 0. For example:





SELECT lname, CONNECT_BY_ISCYCLE

FROM employee

START WITH emp_id = 7839

CONNECT BY NOCYCLE PRIOR emp_id = manager_emp_id;



LNAME CONNECT_BY_ISCYCLE

-------------------- ------------------

KING 0

JONES 0

SCOTT 0

ADAMS 0

FORD 0

SMITH 0

BLAKE 0

ALLEN 0

WARD 0

MARTIN 1

TURNER 0

JAMES 0

CLARK 0

MILLER 0







Since MARTIN is KING's manager in this data set, and

MARTIN also comes under KING in the organization tree, the row for

MARTIN has the value 1 for CONNECT_BY_ISCYCLE.







For correct results in subsequent queries, you should revert our

example data back to its original state by rolling back the earlier

change that forced a cycle in the data. If you have already committed

the previous UPDATE, you should update the

employee table again to set the

manager_emp_id column to NULL for KING.












8.6.4 Identifying Leaf Nodes





In a tree structure, the

nodes at the lowest level of the

tree are referred to as leaf nodes. Leaf nodes have no children.





CONNECT_BY_ISLEAF

is a pseudocolumn that returns 1 if the current row is a leaf, and

returns 0 if the current row is not a leaf. For example:





SELECT lname, CONNECT_BY_ISLEAF

FROM employee

START WITH manager_emp_id IS NULL

CONNECT BY PRIOR emp_id = manager_emp_id;



LNAME CONNECT_BY_ISLEAF

--------------- -----------------

KING 0

JONES 0

SCOTT 0

ADAMS 1

FORD 0

SMITH 1

BLAKE 0

ALLEN 1

WARD 1

MARTIN 1

TURNER 1

JAMES 1

CLARK 0

MILLER 1







This new feature can help simplify SQL statements that need to

identify all the leaf nodes in a hierarchy. Without this

pseudocolumn, to identify the leaf nodes, you would write a query

like the following:





SELECT emp_id, lname, salary, hire_date

FROM employee e

WHERE NOT EXISTS

(SELECT emp_id FROM employee e1 WHERE e.emp_id = e1.manager_emp_id);



EMP_ID LNAME SALARY HIRE_DATE

------- --------------- ---------- ---------

7369 SMITH 800 17-DEC-80

7499 ALLEN 1600 20-FEB-81

7521 WARD 1250 22-FEB-81

7654 MARTIN 1250 28-SEP-81

7844 TURNER 1500 08-SEP-81

7876 ADAMS 1100 23-MAY-87

7900 JAMES 950 03-DEC-81

7934 MILLER 1300 23-JAN-82







However, you can make this query much simpler by using the new

pseudocolumn CONNECT_BY_ISLEAF, as shown here:





SELECT emp_id, lname, salary, hire_date

FROM employee e

WHERE CONNECT_BY_ISLEAF = 1

START WITH manager_emp_id IS NULL

CONNECT BY PRIOR emp_id = manager_emp_id;



EMP_ID LNAME SALARY HIRE_DATE

------- --------------- ---------- ---------

7876 ADAMS 1100 23-MAY-87

7369 SMITH 800 17-DEC-80

7499 ALLEN 1600 20-FEB-81

7521 WARD 1250 22-FEB-81

7654 MARTIN 1250 28-SEP-81

7844 TURNER 1500 08-SEP-81

7900 JAMES 950 03-DEC-81

7934 MILLER 1300 23-JAN-82







This query builds the complete organization tree, and filters out

only the leaf nodes by performing the check CONNECT_BY_ISLEAF = 1.





















     < Day Day Up > 



    Looking Up Machines with nmblookup





    Looking Up
    Machines with nmblookup



    One of the utilities in the basic Samba
    installation is nmblookup, which is a NetBIOS equivalent to nslookup. The
    primary purpose of the utility is to resolve NetBIOS names into IP addresses. Typical
    usages are as follows:



    $ nmblookup KEARNEY
    lang=EN-GB>querying KEARNEY on 192.168.0.255
    lang=EN-GB>192.168.0.19 KEARNEY<00>
    lang=EN-GB> 
    $ nmblookup -M -
    lang=EN-GB>querying __MSBROWSE__ on 192.168.0.255
    lang=EN-GB>192.168.0.11 __MSBROWSE__<01>
    lang=EN-GB> 
    $ nmblookup -A 192.168.0.19
    lang=EN-GB>Looking up status of 192.168.0.19
    received 5 names
    lang=EN-GB>KEARNEY�������� <00> -�������� M <ACTIVE>
    lang=EN-GB>CURTIS��������� <00> - <GROUP> M <ACTIVE>
    lang=EN-GB>KEARNEY�������� <03> -�������� M <ACTIVE>
    lang=EN-GB>KEARNEY�������� <20> -�������� M <ACTIVE>
    lang=EN-GB>CURTIS����� ����<1e> - <GROUP> M <ACTIVE>
    lang=EN-GB>num_good_sends=0 num_good_receives=0


    The first example looks up the named machine
    by doing a subnet broadcast (as can be seen from the .255 address). The
    response shows the IP address, NetBIOS name, and resource-type byte for KEARNEY.
    If the Windows network has a WINS server, you can specify a direct request with
    the
    -U <ip-address>lang=EN-GB> option. The second example is a shortcut for looking up the domain
    master browser, while the third example performs a status inquiry on an IP
    address rather than on a NetBIOS name.



    nmblookup has many more modes of operation. As
    usual, consult the man page for more information.



     





    Section 8.2. Creating a New File


    Working with Files > Creating a New File




    8.2. Creating a New File


    To create a new file and open it at the same time, use the File method new, like this:

    file = File.new( "file.rb", "w" ) # => #<File:file.rb>


    The first argument names the new file, and the second argument specifies the file mode—r for readable, w for writable, or x for executable.


    Table 8-1 shows the effect of the different modes.


































    Table 8-1. File modes
    Mode Description
    "r" Read-only. Starts at beginning of file (default mode).
    "r+" Read-write. Starts at beginning of file.
    "w" Write-only. Truncates existing file to zero length or creates a new file for writing.
    "w+" Read-write. Truncates existing file to zero length or creates a new file for reading and writing.
    "a" Write-only. Starts at end of file if file exists; otherwise, creates a new file for writing.
    "a+" Read-write. Starts at end of file if file exists; otherwise, creates a new file for reading and writing.
    "b" (DOS/Windows only.) Binary file mode. May appear with any of the key letters listed above.













    You can also create files using new with flags and permission bits. For more information, see http://www.ruby-doc.org/core/classes/File.html



     

     


    Section 8.5. Hooks








    8.5. Hooks


    Module, Class, and
    Objectimplement several callback methods, or hooks. These methods are
    not defined by default, but if you define them for a module, class, or
    object, then they will be invoked when certain events occur. This gives
    you an opportunity to extend Ruby's behavior when classes are subclassed,
    when modules are included, or when methods are defined. Hook methods
    (except for some deprecated ones not described here) have names that end in
    "ed."


    When a new class is defined, Ruby invokes the class method inherited on the superclass of the new
    class, passing the new class object as the argument. This allows classes
    to add behavior to or enforce constraints on their descendants. Recall
    that class methods are inherited, so that the an
    inherited method will be invoked if it is defined by
    any of the ancestors of the new class. Define
    Object.inherited to receive notification of all new
    classes that are defined:


    def Object.inherited(c)
    puts "class #{c} < #{self}"
    end



    When a module is included into a class or into another module, the
    included class method of the included module is invoked
    with the class or module object into which it was included as an argument.
    This gives the included module an opportunity to augment or alter the
    class in whatever way it wants—it effectively allows a module to define
    its own meaning for include. In addition to adding
    methods to the class into which it is included, a module with an
    included method might also alter the existing methods
    of that class, for example:


    module Final             # A class that includes Final can't be subclassed
    def self.included(c) # When included in class c
    c.instance_eval do # Define a class method of c
    def inherited(sub) # To detect subclasses
    raise Exception, # And abort with an exception
    "Attempt to create subclass #{sub} of Final class #{self}"
    end
    end
    end
    end



    Similarly, if a module defines a class method named
    extended, that method will be invoked any time the
    module is used to extend an object (with
    Object.extend). The argument to the
    extended method will be the object that was extended,
    of course, and the extended method can take whatever
    actions it wants on that object.


    In addition to hooks for tracking classes and the modules they
    include, there are also hooks for tracking the methods of classes and
    modules and the singleton methods of arbitrary objects. Define a class
    method named method_added for any class or module and
    it will be invoked when an instance method is defined for that class or
    module:


    def String.method_added(name) 
    puts "New instance method #{name} added to String"
    end



    Note that the method_added class method is
    inherited by subclasses of the class on which it is defined. But no class
    argument is passed to the hook, so there is no way to tell whether the
    named method was added to the class that defines
    method_added or whether it was added to a subclass of
    that class. A workaround for this problem is to define an
    inherited hook on any class that defines a
    method_added hook. The inherited
    method can then define a method_added method for each
    subclass.


    When a singleton method is defined for any object, the method
    singleton_method_added is invoked
    on that object, passing the name of the new method. Remember that for classes, singleton methods
    are class methods:


    def String.singleton_method_added(name)
    puts "New class method #{name} added to String"
    end



    Interestingly, Ruby invokes this
    singleton_method_added hook when the hook method itself
    is first defined. Here is another use of the hook. In this case, singleton_method_added is defined as an
    instance method of any class that includes a module. It is notified of any
    singleton methods added to instances of that class:


    # Including this module in a class prevents instances of that class
    # from having singleton methods added to them. Any singleton methods added
    # are immediately removed again.
    module Strict
    def singleton_method_added(name)
    STDERR.puts "Warning: singleton #{name} added to a Strict object"
    eigenclass = class << self; self; end
    eigenclass.class_eval { remove_method name }
    end
    end



    In addition to method_added and
    singleton_method_added, there are hooks for tracking
    when instance methods and singleton methods are removed or undefined. When
    an instance method is removed or undefined on a class or module, the class
    methods method_removed and
    method_undefined are invoked on that module. When a
    singleton method is removed or undefined on an object, the methods
    singleton_method_removed and
    singleton_method_undefined are invoked on that
    object.


    Finally, note that the method_missing and
    const_missing methods documented elsewhere in this chapter also behave like
    hook methods.









    The Player Sprite









    The Player Sprite


    PlayerSprite represents the player and is a subclass of TiledSprite. The statechart for PlayerSprite in Figure 13-14 shows that the sprite performs three concurrent activities.


    The move( ) and tryPickup( ) transitions are triggered by the user from the keyboard. The hitByAlien( ) transition is initiated by the WorldDisplay object when an alien tells it that it has hit the player.


    The transitions in Figure 13-14 are labeled with method names; this is a practice that I'll use when there's a direct mapping from a transition to a method call. This makes it easier to see the mapping from the statechart to the corresponding code.




    Figure 13-14. PlayerSprite statechart




    Moving (and Standing Still)


    A PlayerSprite TRies to move when the user presses one of the quadrant keys (9, 3, 1, or 7):



    public void move(int quad)
    {
    Point newPt = tryMove(quad);
    if (newPt == null) { // move not possible
    clipsLoader.play("slap", false);
    standStill( );
    }
    else { // move is possible
    setTileLoc(newPt); // update the sprite's tile location
    if (quad == NE)
    setImage("ne");
    else if (quad == SE)
    setImage("se");
    else if (quad == SW)

    setImage("sw");
    else // quad == NW
    setImage("nw");
    world.playerHasMoved(newPt, quad);
    }
    } // end of move( )



    The attempt is handled by TiledSprite's inherited tryMove( ) method, and the sprite's tile location is updated if it's successful. The move is dressed up with an image change for the sprite and the playing of a sound effect if the move is blocked.


    The player can press 5 to make the sprite stand still, which only changes its associated image. Normally, the sprite is poised in a running position, pointing in one of the quadrant directions.



    public void standStill( )
    { setImage("still"); }





    Drawing the Player


    The statechart includes a draw state, triggered by a draw( ) transition. The draw activity is implemented by using the setPosition( ) and draw( ) methods inherited from Sprite. The drawing isn't initiated by code in PlayerSprite but is by WorldDisplay's draw( ) method:



    public void draw(Graphics g)
    // in WorldDisplay
    { g.drawImage(floorIm, xOffset, yOffset, null); // draw floor image
    wItems.positionSprites(player, aliens); // add sprites
    wItems.draw(g, xOffset, yOffset); // draw things
    wItems.removeSprites( ); // remove sprites
    }



    As explained earlier, all the sprites, including the player, are added to WorldItems temporarily so they can be drawn in the correct z-order. Each sprite is stored as a TileOccupier object, and setPosition( ) and draw( ) are called from there.




    Being Hit by an Alien


    PlayerSprite maintains a hit counter, which is incremented by a call to hitByAlien( ) from the WorldDisplay object:



    public void hitByAlien( )
    { clipsLoader.play("hit", false);
    hitCount++;
    if (hitCount == MAX_HITS) // player is dead
    atPanel.gameOver( );
    }



    When hitCount reaches a certain value (MAX_HITS), it's all over. The sprite doesn't terminate though; it only notifies AlienTilePanel. This allows AlienTilesPanel to carry out "end of game" tasks, which in this case are reporting the game score and playing a sound clip of applause. AlienTilesPanel could do a lot more, such as ask users if they wanted to play another game. These kinds of game-wide activities should be done at the game panel level and not by a sprite.




    Trying to Pick Up a Pickup


    The user tries to pick up an item by pressing 2 on the numbers keypad. The hard work here is determining if the sprite's current tile location contains a pickup and to remove that item from the scene. The two operations are handled by WorldDisplay methods:



    public boolean tryPickup( )
    {
    String pickupName;
    if ((pickupName = world.overPickup( getTileLoc( ))) == null) {
    clipsLoader.play("noPickup", false); // nothing to pickup
    return false;
    }
    else { // found a pickup
    clipsLoader.play("gotPickup", false);
    world.removePickup(pickupName); // tell WorldDisplay
    return true;
    }
    }



    The name of the pickup on the current tile is obtained and used in the deletion request. If the tile is empty, a sound clip will be played instead.










      Recipe 17.7. Getting and Setting a Transparent Color










      Recipe 17.7. Getting and Setting a Transparent Color



      17.7.2. Problem


      You want
      to set one color in an image as transparent. When the image is overlayed on a background, the background shows through the transparent section of the image.




      17.7.3. Solution


      Use
      ImageColorTransparent( ):


      $color = ImageColorAllocate($image, $red, $green, $blue);
      ImageColorTransparent($image, $color);





      17.7.4. Discussion


      Both GIFs and PNGs support transparencies; JPEGs, however, do not. To refer to the transparent color within GD, use the constant IMG_COLOR_TRANSPARENT. For example, here's how to make a dashed line that alternates between black and transparent:


      // make a two-pixel thick black and white dashed line
      $style = array($black, $black, IMG_COLOR_TRANSPARENT, IMG_COLOR_TRANSPARENT);
      ImageSetStyle($image, $style);



      To find the current transparency setting, take the return value of ImageColorTransparent( ) and pass it to ImageColorsForIndex( ):


      $transparent = ImageColorsForIndex($image, ImageColorTransparent($image));
      print_r($transparent);

      $transparent = ImageColorsForIndex($image, ImageColorTransparent($image));
      print_r($transparent);
      Array
      (
      [red] => 255
      [green] => 255
      [blue] => 255
      )



      The ImageColorsForIndex( ) function returns an array with the red, green, and blue values. In this case, the transparent color is white.




      17.7.5. See Also


      Documentation on ImageColorTransparent( ) at http://www.php.net/imagecolortransparent and on ImageColorsForIndex( ) at http://www.php.net/imagecolorsforindex.