问:
How do I validate the password of a user created with the User Manager?
I want to know how to check an arbitrary password against the validation rules defined in validation.xml. I created an admin page where admin users can create other admin users. I want to validate these users using the same rules that are used when anonymous users register for their own account at the /register page. From what I can see, these rules are defined in validation.xml.

So basically I want to do something like this:

```<code>$userManager = $container->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setPlainPassword('1');
$arrayOfErrors = functionThatValidatesUserPassword($user);
</code>```

or even call a function on the password directly like this:

```<code>$arrayOfErrors = functionThatValidatesUserPassword('1');
</code>```

What should I use to replace functionThatValidatesUserPassword here?

I thought the validator service might work, but when I try

```<code>$validator = $this->get('validator');
$errors = $validator->validate($user);
print_r($errors);exit;
</code>```

I just get an empty list of errors. I was expecting to see an error saying "The password is too short" which is what you get if you register for an account with the same password on the /register page.

I am on Symfony 3.4 and FosUserBundle 2.0.

While searching for answers to my question, I found the following two posts describing how to override the rules defined in the validation.xml file.

fosuserbundle password validation

FOSUserBundle - Validation for username, password or email fields

I do plan on overriding the validation rules, but for now I just want to validate my password using the built-in rules that come with FosUserBundle.

答:
I found the answer to my problem. The constraints in FOSUserBundle's built-in validation.xml belong to validation groups. By default, the validate function only validates for constraints that don't belong to any group. There is a third parameter to the validate function that takes in an array of groups that contain the constraints that you want to check for. So all you have to do is pass in the groups that contain the constraints you want to check. For example, the password field belongs to the following groups: Registration, Profile, ResetPassword, ChangePassword. I used the Registration group, so my code looks like this:

```<code>$userManager = $this->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setPlainPassword('1');
$validator = $this->get('validator', null, array("Registration"));
$errors = $validator->validate($user);
</code>```

Body:
I want to know how to check an arbitrary password against the validation rules defined in validation.xml. I created an admin page where admin users can create other admin users. I want to validate these users using the same rules that are used when anonymous users register for their own account at the /register page. From what I can see, these rules are defined in validation.xml.

So basically I want to do something like this:

$userManager = $container->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setPlainPassword('1');
$arrayOfErrors = functionThatValidatesUserPassword($user);

or even call a function on the password directly like this:

$arrayOfErrors = functionThatValidatesUserPassword('1');

What should I use to replace functionThatValidatesUserPassword here?

I thought the validator service might work, but when I try

$validator = $this->get('validator');
$errors = $validator->validate($user);
print_r($errors);exit;

I just get an empty list of errors. I was expecting to see an error saying "The password is too short" which is what you get if you register for an account with the same password on the /register page.

I am on Symfony 3.4 and FosUserBundle 2.0.

While searching for answers to my question, I found the following two posts describing how to override the rules defined in the validation.xml file.

fosuserbundle password validation

FOSUserBundle - Validation for username, password or email fields

I do plan on overriding the validation rules, but for now I just want to validate my password using the built-in rules that come with FosUserBundle.

Body:
I found the answer to my problem. The constraints in FOSUserBundle's built-in validation.xml belong to validation groups. By default, the validate function only validates for constraints that don't belong to any group. There is a third parameter to the validate function that takes in an array of groups that contain the constraints that you want to check for. So all you have to do is pass in the groups that contain the constraints you want to check. For example, the password field belongs to the following groups: Registration, Profile, ResetPassword, ChangePassword. I used the Registration group, so my code looks like this:

$userManager = $this->get('fos_user.user_manager');
$user = $userManager->createUser();
$user->setPlainPassword('1');
$validator = $this->get('validator', null, array("Registration"));
$errors = $validator->validate($user);


来源: stackexchange

问:
JavaScript - Generating combinations from n arrays with m elements
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.

Consider this data:

```<code>[[0,1], [0,1,2,3], [0,1,2]]
</code>```

3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.

For example:

```<code>0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
</code>```

And so on.

If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:

```<code>[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
</code>```

Any help would be much appreciated.

答:
You could take an iterative approach by building sub arrays.

var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
    result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));

console.log(result.map(a => a.join(', ')));```
<pre class="snippet-code-css lang-css prettyprint-override"><code>.as-console-wrapper { max-height: 100% !important; top: 0; }</code>```

ContentLicense: CC BY-SA 3.0

Body:
I'm having trouble coming up with code to generate combinations from n number of arrays with m number of elements in them, in JavaScript. I've seen similar questions about this for other languages, but the answers incorporate syntactic or library magic that I'm unsure how to translate.

Consider this data:

[[0,1], [0,1,2,3], [0,1,2]]

3 arrays, with a different number of elements in them. What I want to do is get all combinations by combining an item from each array.

For example:

0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2

And so on.

If the number of arrays were fixed, it would be easy to make a hard coded implementation. But the number of arrays may vary:

[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]

Any help would be much appreciated.

Body:
You could take an iterative approach by building sub arrays.

var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
    result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));

console.log(result.map(a => a.join(', ')));

.as-console-wrapper { max-height: 100% !important; top: 0; }


问:
Change Woocommerce "quantity" text in products page for defined product category
I have a product category that I would like to display a different "quantity" text next to the quantity selector.

example: I have a product category called "stone" which has stone countertops which customers enter their square footage. Instead of it saying quantity it would say "enter square footage". This would only apply to the product category "stone" because there are other products in different categories I don't want this on.

答:
add_filter('gettext', 'translate_reply');
add_filter('ngettext', 'translate_reply');

function translate_reply($translated) {

if ( !has_term( 'stone', 'product_cat' ) ) {
   $translated = str_ireplace('Quantity', 'Quantity', $translated);
    return $translated;

 }else{
   $translated = str_ireplace('Quantity', 'Enter Square Feet', $translated);
    return $translated;
 }
}```


问:
Spark filter dataframe returns empty result
I'm working in a project with Scala and Spark processing files that are stored in HDFS. Those files are landing in HDFS everyday in the morning. I have a job that reads that file from HDFS each day, process it and then writes the result in HDFS. After I convert the file into a Dataframe, this job executes a filter to get only the rows that contain a timestamp higher than the highest timestamp that was processed within the last file. This filter has an unknown behavior only some days. Some days works as expected and other days despite of the new file contains rows that match that filter, the filter result is empty. This happens all the times for the same file when it's executed in TEST environment but in my local works as expected using the same file with the same HDFS connection.

I've tried to filter in different ways but none of then work in that environment for some specific files but all of then work fine in my LOCAL:
1) Spark sql

```<code>val diff = fp.spark.sql("select * from curr " +
s"where TO_DATE(CAST(UNIX_TIMESTAMP(substring(${updtDtCol},
${substrStart},${substrEnd}),'${dateFormat}') as TIMESTAMP))" +
s" > TO_DATE(CAST(UNIX_TIMESTAMP('${prevDate.substring(0,10)}'
,'${dateFormat}') as TIMESTAMP))")
</code>```

2) Spark filter functions

```<code>val diff = df.filter(date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)))
</code>```

3) Adding extra column with the result of the filter and then filter by this new column

```<code>val test2 = df.withColumn("PrevDate", lit(prevDate.substring(0,10)))
      .withColumn("DatePre", date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat))
      .withColumn("Result", date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)))
      .withColumn("x", when(date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)), lit(1)).otherwise(lit(0)))

val diff = test2.filter("x == 1")
</code>```

I think that the issue is not caused either by the filter itself or probably by the file but I would like to receive feedback about what should I check or if anybody has faced this before.

Please let me know what information could be useful to post here in order to receive some feedback.

A part of file example looks like the following:

```<code>|TIMESTAMP                 |Result|x|
|2017-11-30-06.46.41.288395|true  |1|
|2017-11-28-08.29.36.188395|false |0|
</code>```

The TIMESTAMP values are compared with the previousDate (for instance: 2017-11-29) and I create a column called 'Result' with the result of that comparison that always works in both environment and also another column called 'x' with the same result.

As I mentioned before, if I use the comparator function between both dates or the result in column 'Result' or 'x' to filter the dataframe, sometimes the result is an empty dataframe but in local using the same HDFS and file, the result contains data.

答:
I suspect it to be a data/date format issue. Did you get a chance to verify if the dates converted are as expected?

If the date string for both the columns has timezone included, the behavior is predictable.

If only of one of them has timezone included, the results will be different when executed in local and remote. It totally depends on timezone of cluster.

For debugging the issue, I would suggest you to have additional columns to capture the unix_timestamp(..)/millis of the respective date strings and have and additional column to capture the difference of the two columns. The diff column should help to find out where and why conversions gone wrong. Hope this helps.

Body:
I'm working in a project with Scala and Spark processing files that are stored in HDFS. Those files are landing in HDFS everyday in the morning. I have a job that reads that file from HDFS each day, process it and then writes the result in HDFS. After I convert the file into a Dataframe, this job executes a filter to get only the rows that contain a timestamp higher than the highest timestamp that was processed within the last file. This filter has an unknown behavior only some days. Some days works as expected and other days despite of the new file contains rows that match that filter, the filter result is empty. This happens all the times for the same file when it's executed in TEST environment but in my local works as expected using the same file with the same HDFS connection.

I've tried to filter in different ways but none of then work in that environment for some specific files but all of then work fine in my LOCAL:
1) Spark sql

val diff = fp.spark.sql("select * from curr " +
s"where TO_DATE(CAST(UNIX_TIMESTAMP(substring(${updtDtCol},
${substrStart},${substrEnd}),'${dateFormat}') as TIMESTAMP))" +
s" > TO_DATE(CAST(UNIX_TIMESTAMP('${prevDate.substring(0,10)}'
,'${dateFormat}') as TIMESTAMP))")

2) Spark filter functions

val diff = df.filter(date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)))

3) Adding extra column with the result of the filter and then filter by this new column

val test2 = df.withColumn("PrevDate", lit(prevDate.substring(0,10)))
      .withColumn("DatePre", date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat))
      .withColumn("Result", date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)))
      .withColumn("x", when(date_format(unix_timestamp(substring(col(updtDtCol),0,10),dateFormat).cast("timestamp"),dateFormat).gt(date_format(unix_timestamp(substring(col("PrevDate"),0,10),dateFormat).cast("timestamp"),dateFormat)), lit(1)).otherwise(lit(0)))

val diff = test2.filter("x == 1")

I think that the issue is not caused either by the filter itself or probably by the file but I would like to receive feedback about what should I check or if anybody has faced this before.

Please let me know what information could be useful to post here in order to receive some feedback.

A part of file example looks like the following:

|TIMESTAMP                 |Result|x|
|2017-11-30-06.46.41.288395|true  |1|
|2017-11-28-08.29.36.188395|false |0|

The TIMESTAMP values are compared with the previousDate (for instance: 2017-11-29) and I create a column called 'Result' with the result of that comparison that always works in both environment and also another column called 'x' with the same result.

As I mentioned before, if I use the comparator function between both dates or the result in column 'Result' or 'x' to filter the dataframe, sometimes the result is an empty dataframe but in local using the same HDFS and file, the result contains data.


问:
NSView enterFullScreenWithOptions: scaling the NSView
So, in reference to : Kiosk Applications - OS X programming - Multiple monitors

I have an 800x600 NSView and I need to scale this proportionally when I enter full screen mode using NSView's enterFullScreenModeWithOptions.

Right now, what's happening is the UI elements are stationary at where they were initially defined and the view is occupying the full screen mode. To top this off, my view has a background image which occupies the top left 800x600 square on the monitor too. So how do I scale everything in the view proportionally to fit the screen when in full screen mode?

Thanks again,

Teja

答:
I implemented a viewer, which inherits form NSView. Before my image gets drawn, I do the resize [image setSize:size] to fit my image to the fullscreen.

```<code>if([myviewer isInFullScreenMode]){
    int width = [[NSScreen mainScreen] frame].size.width;
    int height = [[NSScreen mainScreen] frame].size.height;

    NSSize size;

    size.width = width;
    size.height = height;

    [image setScalesWhenResized:YES];
    [image setSize:size];
}
</code>```

Hope, this can help anyone.

ContentLicense: CC BY-SA 2.5

Body:
I implemented a viewer, which inherits form NSView. Before my image gets drawn, I do the resize [image setSize:size] to fit my image to the fullscreen.

if([myviewer isInFullScreenMode]){
    int width = [[NSScreen mainScreen] frame].size.width;
    int height = [[NSScreen mainScreen] frame].size.height;

    NSSize size;

    size.width = width;
    size.height = height;

    [image setScalesWhenResized:YES];
    [image setSize:size];
}

Hope, this can help anyone.


问:
TSQL MERGE with multiple sources
Originally i tried using an IF/ELSE to accomplish an "UPSERT" and someone suggested I use MERGE my issue with MERGE is it does not look like I can use two sources.

Here is my Original attempt at an upsert:

```<code>IF ((SELECT COUNT(CAST(StudentuserID AS int)) FROM HL_StudentAttendance WHERE StudentUserID=1)>0)
UPDATE HL_StudentAttendance
SET
CID = CAST('[querystring:CID]' AS int),
CalendarEventID = CAST('[querystring:CEID]' AS int),
StudentUserID = CAST('[StudentUserID]' AS int),
Attendance = '[Attendance]'
ELSE
INSERT INTO HL_StudentAttendance
(CID,CalendarEventID,StudentUserID,Attendance)
VALUES
(CAST('[querystring:CID]' AS int), CAST('[querystring:CEID]' AS int), CAST('[StudentsUserID]' AS int),'[Attendance]')
</code>```

Even though the IF statement result is 8 so 8>0 it should run my update it's always running an insert not sure if my if/else logic is missing something.

Here is an attempt with MERGE

```<code>MERGE
   HL_StudentAttendance AS target
USING
   HL_CourseRegistrations AS source
ON
   target.StudentUserID = source.UserID
   AND source.
WHEN MATCHED THEN
   UPDATE SET
   Attendance = '[Attendance]'
WHEN NOT MATCHED THEN
   INSERT (CID, CalendarEventID, StudentUserID, Attendance) VALUES ('[querystring:CID]', '[querystring:CEID]', '[UserID]', '[Attendance]')
;
</code>```

My issue here is that I have data in my table HL_CourseEvents that should be used to grab an additional source item being CalendarEventID otherwise the MERGE works but inserts duplicate entries into my HL_StudentAttendance as there is no parameter for CalendarEventID

Any suggestions appreciated.

UPDATE

The following query does work, except that it's inserting new records if anything is changed on the attendance field rather than update properly. I suspect because the WHERE clause on my update is not there. I tried adding it getting execution errors

```<code>MERGE HL_StudentAttendance
USING
(
SELECT cr.CID, ce.CalendarEventID, cr.UserID FROM HL_CourseRegistrations cr
JOIN HL_CalendarEvents ce
ON ce.CID = cr.CID
) tmpTable
ON
HL_StudentAttendance.StudentUserID = tmpTable.UserID
AND HL_StudentAttendance.CalendarEventID = tmpTable.CalendarEventID
WHEN MATCHED THEN
UPDATE
SET
Attendance = 'Attended Late'
WHEN NOT MATCHED THEN
INSERT (CID,CalendarEventID,StudentUserID,Attendance) VALUES ('1','1','1','555')
;
</code>```

Results of the query run twice. If i keep running it, it will always insert more instead of updating:

```<code>ID  CID CalendarEventID StudentUserID Attendance
1   1   1               1             Attended Late
2   1   1               1             Attended Late
3   1   1               1             Attended Late
4   1   1               1             Attended Late
5   1   1               1             Attended Late
6   1   1               1             555
7   1   1               1             555
8   1   1               1             555
9   1   1               1             555
</code>```

答:
Based on additional information, try this below. I've hacked together a schema and some data for demonstration purposes only so you'll have to see how your schema compares. However, the two examples at the bottom do what you're asking I believe. The first inserts a new record if it does not exist based on the user id. The second marks that record as "Attended late" if it exists. Note that, for real life you're probably going to need multiple parameters as a user could be signed up for multiple courses, so you'll want to pass in the course or calendar event id as well. Let me know if this gets you started or you need something additional.</p>

```<code>--
-------------------------------------------------
CREATE TABLE [test].[HL_StudentAttendance]
  (
       [StudentUserID]     INT
       , [CalendarEventID] INT
       , [Attendance]      NVARCHAR(250)
       , [CID]             INT
  );

CREATE TABLE [test].[HL_CourseRegistrations]
  (
       [CID]      INT
       , [UserID] INT
  );

CREATE TABLE [test].[HL_CalendarEvents]
  (
       [CalendarEventID] INT
       , [CID]           INT
  );

go

--
-------------------------------------------------
INSERT INTO [test].[HL_CourseRegistrations]
            ([CID]
             , [UserId])
VALUES      (1,1),
            (3,4),
            (4,5);

INSERT INTO [test].[HL_CalendarEvents]
            ([CalendarEventID]
             , [CID])
VALUES      (1,1);

go

--
-------------------------------------------------
CREATE PROCEDURE [test].[set_attendance] @user INT
AS
    BEGIN
        MERGE INTO [test].[HL_StudentAttendance] AS [target]
        USING (SELECT [cr].[CID]
                      , [ce].[CalendarEventID]
                      , [cr].[UserID]
               FROM   [test].[HL_CourseRegistrations] [cr]
                      JOIN [test].[HL_CalendarEvents] [ce]
                        ON [ce].[CID] = [cr].[CID]) AS [source]
        ON [target].[StudentUserID] = @user
           AND [target].[CalendarEventID] = [source].[CalendarEventID]
        WHEN MATCHED THEN
            UPDATE SET [Attendance] = 'Attended Late'
        WHEN NOT MATCHED BY target THEN
            INSERT ([CID]
                    , [CalendarEventID]
                    , [StudentUserID]
                    , [Attendance])
            VALUES ('1'
                    , '1'
                    , @user
                    , '555');
    END;

go

--
-- inserts a new record
-------------------------------------------------
EXECUTE [test].[set_attendance]
    @user=12;

SELECT *
FROM   [test].[HL_StudentAttendance];

--
-- marks an existing record as late
-------------------------------------------------
EXECUTE [test].[set_attendance]
    @user=12;

SELECT *
FROM   [test].[HL_StudentAttendance];
</code>```

Title: TSQL MERGE with multiple sources

Body:
Originally i tried using an IF/ELSE to accomplish an "UPSERT" and someone suggested I use MERGE my issue with MERGE is it does not look like I can use two sources.

Here is my Original attempt at an upsert:

IF ((SELECT COUNT(CAST(StudentuserID AS int)) FROM HL_StudentAttendance WHERE StudentUserID=1)>0)
UPDATE HL_StudentAttendance
SET
CID = CAST('[querystring:CID]' AS int),
CalendarEventID = CAST('[querystring:CEID]' AS int),
StudentUserID = CAST('[StudentUserID]' AS int),
Attendance = '[Attendance]'
ELSE
INSERT INTO HL_StudentAttendance
(CID,CalendarEventID,StudentUserID,Attendance)
VALUES
(CAST('[querystring:CID]' AS int), CAST('[querystring:CEID]' AS int), CAST('[StudentsUserID]' AS int),'[Attendance]')

Even though the IF statement result is 8 so 8>0 it should run my update it's always running an insert not sure if my if/else logic is missing something.

Here is an attempt with MERGE

MERGE
   HL_StudentAttendance AS target
USING
   HL_CourseRegistrations AS source
ON
   target.StudentUserID = source.UserID
   AND source.
WHEN MATCHED THEN
   UPDATE SET
   Attendance = '[Attendance]'
WHEN NOT MATCHED THEN
   INSERT (CID, CalendarEventID, StudentUserID, Attendance) VALUES ('[querystring:CID]', '[querystring:CEID]', '[UserID]', '[Attendance]')
;

My issue here is that I have data in my table HL_CourseEvents that should be used to grab an additional source item being CalendarEventID otherwise the MERGE works but inserts duplicate entries into my HL_StudentAttendance as there is no parameter for CalendarEventID

Any suggestions appreciated.

UPDATE

The following query does work, except that it's inserting new records if anything is changed on the attendance field rather than update properly. I suspect because the WHERE clause on my update is not there. I tried adding it getting execution errors

MERGE HL_StudentAttendance
USING
(
SELECT cr.CID, ce.CalendarEventID, cr.UserID FROM HL_CourseRegistrations cr
JOIN HL_CalendarEvents ce
ON ce.CID = cr.CID
) tmpTable
ON
HL_StudentAttendance.StudentUserID = tmpTable.UserID
AND HL_StudentAttendance.CalendarEventID = tmpTable.CalendarEventID
WHEN MATCHED THEN
UPDATE
SET
Attendance = 'Attended Late'
WHEN NOT MATCHED THEN
INSERT (CID,CalendarEventID,StudentUserID,Attendance) VALUES ('1','1','1','555')
;

Results of the query run twice. If i keep running it, it will always insert more instead of updating:

ID  CID CalendarEventID StudentUserID Attendance
1   1   1               1             Attended Late
2   1   1               1             Attended Late
3   1   1               1             Attended Late
4   1   1               1             Attended Late
5   1   1               1             Attended Late
6   1   1               1             555
7   1   1               1             555
8   1   1               1             555
9   1   1               1             555

Body:
Based on additional information, try this below. I've hacked together a schema and some data for demonstration purposes only so you'll have to see how your schema compares. However, the two examples at the bottom do what you're asking I believe. The first inserts a new record if it does not exist based on the user id. The second marks that record as "Attended late" if it exists. Note that, for real life you're probably going to need multiple parameters as a user could be signed up for multiple courses, so you'll want to pass in the course or calendar event id as well. Let me know if this gets you started or you need something additional.

--
-------------------------------------------------
CREATE TABLE [test].[HL_StudentAttendance]
  (
       [StudentUserID]     INT
       , [CalendarEventID] INT
       , [Attendance]      NVARCHAR(250)
       , [CID]             INT
  );

CREATE TABLE [test].[HL_CourseRegistrations]
  (
       [CID]      INT
       , [UserID] INT
  );

CREATE TABLE [test].[HL_CalendarEvents]
  (
       [CalendarEventID] INT
       , [CID]           INT
  );

go

--
-------------------------------------------------
INSERT INTO [test].[HL_CourseRegistrations]
            ([CID]
             , [UserId])
VALUES      (1,1),
            (3,4),
            (4,5);

INSERT INTO [test].[HL_CalendarEvents]
            ([CalendarEventID]
             , [CID])
VALUES      (1,1);

go

--
-------------------------------------------------
CREATE PROCEDURE [test].[set_attendance] @user INT
AS
    BEGIN
        MERGE INTO [test].[HL_StudentAttendance] AS [target]
        USING (SELECT [cr].[CID]
                      , [ce].[CalendarEventID]
                      , [cr].[UserID]
               FROM   [test].[HL_CourseRegistrations] [cr]
                      JOIN [test].[HL_CalendarEvents] [ce]
                        ON [ce].[CID] = [cr].[CID]) AS [source]
        ON [target].[StudentUserID] = @user
           AND [target].[CalendarEventID] = [source].[CalendarEventID]
        WHEN MATCHED THEN
            UPDATE SET [Attendance] = 'Attended Late'
        WHEN NOT MATCHED BY target THEN
            INSERT ([CID]
                    , [CalendarEventID]
                    , [StudentUserID]
                    , [Attendance])
            VALUES ('1'
                    , '1'
                    , @user
                    , '555');
    END;

go

--
-- inserts a new record
-------------------------------------------------
EXECUTE [test].[set_attendance]
    @user=12;

SELECT *
FROM   [test].[HL_StudentAttendance];

--
-- marks an existing record as late
-------------------------------------------------
EXECUTE [test].[set_attendance]
    @user=12;

SELECT *
FROM   [test].[HL_StudentAttendance];


问:
How to unit test with a recursive object
I have an object that takes in a parameter of the same type in the constructor:

```<code>public class Person {
    private Person theParent;
    private string theName;
    public Person(string aName, Person aParent)
    {
        if(aParent == null)
        {
            thrown new ArgumentNullException("aParent");
        }
        theParent = aParent;
        theName = aName;
    }
}
</code>```

In my unit test I have to create a new Person object but the constructor requires another Person object to be passed in.  I overcome this problem in my application by getting the Person object to pass in from the database (using NHibernate and all its magic)*.  I don't want to tie database access into this test as it is not testing any database functionality.  Should I just mock the parent object (I'm using Rhino Mocks in some of my other tests) or is there a better way to approach this?

*There is guaranteed to always be one record in the databse that I can retrieve to make the parent object.

答: You may test side effects of the recursive function call, e.g. use counter field variable to check number of calls, store call parameter at some kind of container where Unit Test can check them etc. Of course, you will remove all these things in the release build.</p>

Body:
I have an object that takes in a parameter of the same type in the constructor:

public class Person {
    private Person theParent;
    private string theName;
    public Person(string aName, Person aParent)
    {
        if(aParent == null)
        {
            thrown new ArgumentNullException("aParent");
        }
        theParent = aParent;
        theName = aName;
    }
}

In my unit test I have to create a new Person object but the constructor requires another Person object to be passed in.  I overcome this problem in my application by getting the Person object to pass in from the database (using NHibernate and all its magic)*.  I don't want to tie database access into this test as it is not testing any database functionality.  Should I just mock the parent object (I'm using Rhino Mocks in some of my other tests) or is there a better way to approach this?

*There is guaranteed to always be one record in the databse that I can retrieve to make the parent object.


问:
Compare every item in a vector to every other item, while deleting some elements?
I need to write a function which compares every element of an std::vector<std::shared_ptr<Shape >> shapes_ to every other element determine if the shapes overlap, and then remove one of the overlapping shapes if so. Here is what I've got currently:

```<code>class Shape {
    public:
    ...
        virtual bool overlaps(const std::shared_ptr<Shape>&) const = 0;
    ...
};

class Square : public Shape { ... } ;
class Circle : public Shape { ... } ;
</code>```

And utilizing these classes:

```<code>std::vector<shared_ptr<Shape>> shapes_;

// ... some code populates the array

for (auto& shape : shapes_) {
    // Compare to every other shape
    for (unsigned long j = 0; j < shapes_.size(); j++) {
        // If they overlap and they aren't the same shape
        if (shape->overlaps(shapes_.at(j)) && shape!=shapes_.at(j)) {
            shapes_.erase(shapes_.begin() + j);
        }
    }
}
</code>```

However I keep running into problems where I'm iterating over a null (removed) element, or beyond the end of the array or something. I keep re configuring it this way or the other but one of these problems keeps popping up.

What would be considered the most sensible, clean way to deal with a problem where you're comparing every element of a vector to every other element, and in the process sometimes deleting some elements?

Additionally, what if I would like to print some information about each overlap that is found, and the shape that is removed?

答:
You can use erase-remove idiom:

```<code>auto it = vec.begin();
auto end = vec.end();
while( std::distance( it, end ) > 1 ) {
     auto condition = [shape=*it]( const auto &other ) { return shape->overlaps( other ); };
     end = std::remove_if( ++it, end, condition );
}
vec.erase( end, vec.end() );
</code>```

this lambda syntax requires C++14, but it can be easily modified to work with C++11 if necessary (by introducing temp variable shape before lambda for example, or capturing it by value not reference).

Body:
I need to write a function which compares every element of an std::vector<std::shared_ptr<Shape >> shapes_ to every other element determine if the shapes overlap, and then remove one of the overlapping shapes if so. Here is what I've got currently:

class Shape {
    public:
    ...
        virtual bool overlaps(const std::shared_ptr<Shape>&) const = 0;
    ...
};

class Square : public Shape { ... } ;
class Circle : public Shape { ... } ;

And utilizing these classes:

std::vector<shared_ptr<Shape>> shapes_;

// ... some code populates the array

for (auto& shape : shapes_) {
    // Compare to every other shape
    for (unsigned long j = 0; j < shapes_.size(); j++) {
        // If they overlap and they aren't the same shape
        if (shape->overlaps(shapes_.at(j)) && shape!=shapes_.at(j)) {
            shapes_.erase(shapes_.begin() + j);
        }
    }
}

However I keep running into problems where I'm iterating over a null (removed) element, or beyond the end of the array or something. I keep re configuring it this way or the other but one of these problems keeps popping up.

What would be considered the most sensible, clean way to deal with a problem where you're comparing every element of a vector to every other element, and in the process sometimes deleting some elements?

Additionally, what if I would like to print some information about each overlap that is found, and the shape that is removed?

Body:
You can use erase-remove idiom:

auto it = vec.begin();
auto end = vec.end();
while( std::distance( it, end ) > 1 ) {
     auto condition = [shape=*it]( const auto &other ) { return shape->overlaps( other ); };
     end = std::remove_if( ++it, end, condition );
}
vec.erase( end, vec.end() );

this lambda syntax requires C++14, but it can be easily modified to work with C++11 if necessary (by introducing temp variable shape before lambda for example, or capturing it by value not reference).


问:
How to get detailed memory breakdown in the TensorFlow profiler?
I'm using the new TensorFlow profiler to profile memory usage in my neural net, which I'm running on a Titan X GPU with 12GB RAM. Here's some example output when I profile my main training loop:

```<code>==================Model Analysis Report======================
node name | requested bytes | ...
Conv2DBackpropInput        10227.69MB (100.00%, 35.34%),     ...
Conv2D                       9679.95MB (64.66%, 33.45%),     ...
Conv2DBackpropFilter         8073.89MB (31.21%, 27.90%),     ...
</code>```

Obviously this adds up to more than 12GB, so some of these matrices must be in main memory while others are on the GPU. I'd love to see a detailed breakdown of what variables are where at a given step. Is it possible to get more detailed information on where various parameters are stored (main or GPU memory), either with the profiler or otherwise?

答:
"Requested bytes" shows a sum over all memory allocations, but that memory can be allocated and de-allocated. So just because "requested bytes" exceeds GPU RAM doesn't necessarily mean that memory is being transferred to CPU.

In particular, for a feedforward neural network, TF will normally keep around the forward activations, to make backprop efficient, but doesn't need to keep the intermediate backprop activations, i.e. dL/dh at each layer, so it can just throw away these intermediates after it's done with these. So I think in this case what you care about is the memory used by Conv2D, which is less than 12 GB.

You can also use the timeline to verify that total memory usage never exceeds 12 GB.

Body:
I'm using the new TensorFlow profiler to profile memory usage in my neural net, which I'm running on a Titan X GPU with 12GB RAM. Here's some example output when I profile my main training loop:

==================Model Analysis Report======================
node name | requested bytes | ...
Conv2DBackpropInput        10227.69MB (100.00%, 35.34%),     ...
Conv2D                       9679.95MB (64.66%, 33.45%),     ...
Conv2DBackpropFilter         8073.89MB (31.21%, 27.90%),     ...

Obviously this adds up to more than 12GB, so some of these matrices must be in main memory while others are on the GPU. I'd love to see a detailed breakdown of what variables are where at a given step. Is it possible to get more detailed information on where various parameters are stored (main or GPU memory), either with the profiler or otherwise?


问:
waitpid returns 0 when SIGINT (Crtl+c) on a children
I'm working in a terminal for an university work, but I'm having troubles when looking for finished children.

I have a list in which i save the background processes and this works fine, but when i bring it to the foreground and i send him a SIGINT signal with ctrl+c the waitpid returns 1 on all unfinished children but the one I kill. That's my code. I'm sure that my error is in that waitpid, but I don't know why returns a wrong value. What I want my code to do is to select when I kill a process with SIGINT and kill this one and remove this from the list but keep the unfinished commands.

```<code>int emptyBackground(List *list){

    ListNode *aux = list->first;
    ListNode *aux2 = NULL;

    while(aux != NULL){
        if(waitpid(aux->pid, NULL, WNOHANG) > 0){ // This waitpid returns a non expected value
            if(aux2 != NULL){
                aux2->next = aux->next;
                free(aux);
                aux = aux2->next;
            }else{
                list->first = aux->next;
                free(aux);
                aux = list->first;
            }
        }else{
            aux2 = aux;
            aux = aux->next;
        }
    }
    return 0;
}
</code>```

PD: My list has the command pid, the command and a pointer to the next node.

答: waitpid should never return 1. It should return either -1, 0, or the pid of the child that exited. Try using the wstatus field of waitpid to debug exactly what waitpid thinks happened to the child.

Body:
I'm working in a terminal for an university work, but I'm having troubles when looking for finished children.

I have a list in which i save the background processes and this works fine, but when i bring it to the foreground and i send him a SIGINT signal with ctrl+c the waitpid returns 1 on all unfinished children but the one I kill. That's my code. I'm sure that my error is in that waitpid, but I don't know why returns a wrong value. What I want my code to do is to select when I kill a process with SIGINT and kill this one and remove this from the list but keep the unfinished commands.

int emptyBackground(List *list){

    ListNode *aux = list->first;
    ListNode *aux2 = NULL;

    while(aux != NULL){
        if(waitpid(aux->pid, NULL, WNOHANG) > 0){ // This waitpid returns a non expected value
            if(aux2 != NULL){
                aux2->next = aux->next;
                free(aux);
                aux = aux2->next;
            }else{
                list->first = aux->next;
                free(aux);
                aux = list->first;
            }
        }else{
            aux2 = aux;
            aux = aux->next;
        }
    }
    return 0;
}

PD: My list has the command pid, the command and a pointer to the next node.


问:
Why bother using lambda expressions in logging APIs if the compiler can possibly inline the logging call
Many logging frameworks (e.g., log4j) allow you to pass lambda expressions instead of Strings to the logging API. The argument is that if the string is particularly expressive to construct, the string construction can be lazily executed via the lambda expression. That way, the string is only constructed if the system's log level matches that of the call.

But, given that modern compilers do much method inlining automatically, is there really a point to using lambda expressions in this way? I'll supply a simplified example below to demonstrate this concern.

Suppose our traditional logging method looks like this:

```<code>void log(int level, String message) {
    if (level >= System.logLevel)
        System.out.println(message);
}
// ....
System.logLevel = Level.CRITICAL;
log(Level.FINE, "Very expensive string to construct ..." + etc);
</code>```

Let's suppose that FINE is less than CRITICAL, so, although an expensive string is constructed, it's all for not since the message is not outputted.

Lambda logging APIs help this situation so that the string is only evaluated (constructed) when necessary:

```<code>void log(int level, Supplier<String> message) {
    if (level >= System.logLevel)
        System.out.println(message.apply());
}
// ....
System.logLevel = Level.CRITICAL;
log(Level.FINE, () -> "Very expensive string to construct ..." + etc);
</code>```

But, it's feasible that the compiler can just inline the logging method so that the net effect is as follows:

```<code>System.logLevel = Level.CRITICAL;
if (Level.FINE >= System.logLevel)
    System.out.println("Very expensive string to construct..." + etc);
</code>```

In this case, we don't have to evaluate the string prior to the logging API call (because there is none), and presumably, we would gain performance from just the inlining.

In summary, my question is, how do lambda expressions help us in this situation given that the compiler can possibly inline logging API calls? The only thing I can think of is that, somehow, in the lambda case, the string is not evaluate if the logging level is not a match.

答:
Raffi lets look at an example on how the compiler inlining you are talking about will change the program logic and compiler needs to be very smart enough to be able to figure that out:

```<code>   public String process(){
        //do some important bussiness logic
        return "Done processing";
    }
</code>```

1) Without inlining the process() will be callled regardless of logging level:

```<code>log( Level.FINE, "Very expensive string to construct ..." + process() );
</code>```

2) With inlining the process() will be called only under certain logging level and our important bussiness logic wont be able to run:

```<code>if (Level.FINE >= System.logLevel)
    System.out.println("Very expensive string to construct..." +  process() );
</code>```

The compiler in this case has to figure out how the message string is created and not inline the method if it calls any other method during its creation.

Body:
Many logging frameworks (e.g., log4j) allow you to pass lambda expressions instead of Strings to the logging API. The argument is that if the string is particularly expressive to construct, the string construction can be lazily executed via the lambda expression. That way, the string is only constructed if the system's log level matches that of the call.

But, given that modern compilers do much method inlining automatically, is there really a point to using lambda expressions in this way? I'll supply a simplified example below to demonstrate this concern.

Suppose our traditional logging method looks like this:

void log(int level, String message) {
    if (level >= System.logLevel)
        System.out.println(message);
}
// ....
System.logLevel = Level.CRITICAL;
log(Level.FINE, "Very expensive string to construct ..." + etc);

Let's suppose that FINE is less than CRITICAL, so, although an expensive string is constructed, it's all for not since the message is not outputted.

Lambda logging APIs help this situation so that the string is only evaluated (constructed) when necessary:

void log(int level, Supplier<String> message) {
    if (level >= System.logLevel)
        System.out.println(message.apply());
}
// ....
System.logLevel = Level.CRITICAL;
log(Level.FINE, () -> "Very expensive string to construct ..." + etc);

But, it's feasible that the compiler can just inline the logging method so that the net effect is as follows:

System.logLevel = Level.CRITICAL;
if (Level.FINE >= System.logLevel)
    System.out.println("Very expensive string to construct..." + etc);

In this case, we don't have to evaluate the string prior to the logging API call (because there is none), and presumably, we would gain performance from just the inlining.

In summary, my question is, how do lambda expressions help us in this situation given that the compiler can possibly inline logging API calls? The only thing I can think of is that, somehow, in the lambda case, the string is not evaluate if the logging level is not a match.

Body:
Raffi lets look at an example on how the compiler inlining you are talking about will change the program logic and compiler needs to be very smart enough to be able to figure that out:

   public String process(){
        //do some important bussiness logic
        return "Done processing";
    }

1) Without inlining the process() will be callled regardless of logging level:

log( Level.FINE, "Very expensive string to construct ..." + process() );

2) With inlining the process() will be called only under certain logging level and our important bussiness logic wont be able to run:

if (Level.FINE >= System.logLevel)
    System.out.println("Very expensive string to construct..." +  process() );

The compiler in this case has to figure out how the message string is created and not inline the method if it calls any other method during its creation.


问:
How to call a function every 3 seconds using Swift Spritekit
In normal swift, you can use something like this:

```<code>Foundation.Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(GameViewController.hideFunc), userInfo: nil, repeats: true)
</code>```

My question is what can you replace this with to work in a Sprite kit game?

答:
Well, you could build it pretty easily using SKActions:

```<code>    let pauser = SKAction.wait(forDuration: 3.0)
    let trigger = SKAction.perform(#selector(GameViewController.hideFunc, onTarget: self)
    let pauseThenTrigger = SKAction.sequence([ pauser, trigger ])
    let repeatForever = SKAction.repeatForever(pauseThenTrigger)
    node.run( repeatForever )
</code>```

This approach would have the virtue of letting you reuse this action for any nodes that would need to use it, and you can easily control the action by removing or adding the node from the scene, calling removeAllActions() on it, etc.

Body:
In normal swift, you can use something like this:

Foundation.Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(GameViewController.hideFunc), userInfo: nil, repeats: true)

My question is what can you replace this with to work in a Sprite kit game?

Body:
Well, you could build it pretty easily using SKActions:

    let pauser = SKAction.wait(forDuration: 3.0)
    let trigger = SKAction.perform(#selector(GameViewController.hideFunc, onTarget: self)
    let pauseThenTrigger = SKAction.sequence([ pauser, trigger ])
    let repeatForever = SKAction.repeatForever(pauseThenTrigger)
    node.run( repeatForever )

This approach would have the virtue of letting you reuse this action for any nodes that would need to use it, and you can easily control the action by removing or adding the node from the scene, calling removeAllActions() on it, etc.


问:
Get name from variable in calling method - creating calling method signature, parameters and values
I'm looking for a way to get hold of the name of a variable that was passed into an extensionmethod. I want to have the name of the parameter in the calling variable. Sounds strange, let me explain.

assume this piece of testing code

```<code>    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help");
        }
    }
</code>```

On the last line you can see the exception being logged. I want to be able to provide optional parameter support. So the developers can add parameter information when needed.

I've seen many posts about this on stackoverflow, lot's of different approaches. Main thing is; it can't be done fully generically.

Some code for explanation:

```<code>    static string GetCallingMethodSignature()
    {
        StackTrace stackTrace = new StackTrace();

        // Get calling method name
        var callingMethod = stackTrace.GetFrame(1).GetMethod();
        var callingMethod_Name = callingMethod.Name;

        // get calling method params
        string retVal = string.Empty;

        var callingMethod_Parameters = callingMethod.GetParameters();

        retVal = callingMethod_Name + "(";
        foreach (var param in callingMethod_Parameters)
        {
            retVal += param.Name + ": " + param.ToString() + ",";
        }
        retVal.Remove(retVal.Length - 1, 1);
        retVal += ")";

        return retVal;
    }
</code>```

Now, this testing code is getting the calling method name and it's parameters. That is, the names of the parameters. But not their values. The param.tostring() part only returns the type name. Not the value. I've been reading on this and it seems this can't be done via reflection.

So then I went for another approach, why not provide the parameters the developer finds suitable for logging. You don't need all of them most of the time anyway.

```<code>private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)
</code>```

So, this being a new testmethod, i'm providing the parameters of choice into the exception logging method. But if you want to make this work, it's one hell of a job everytime to make this call.

```<code>    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
                new KeyValuePair<string, object>("firstParam", firstParam),
                new KeyValuePair<string, object>("secondParam", secondParam),
                new KeyValuePair<string, object>("thirdParam", thirdParam)
            });
        }
    }
</code>```

Now this is working. But as said, i find the bottom part to cumbersome. I was thinking along the lines of an extensionmethod, so I can shorten the creation of each kvp.

```<code>internal static class ExtensionMethodsForTesting
{
    internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
    {
        var name = nameof(parameter);
        return new KeyValuePair<string, object>(name, parameter);
    }
}
</code>```

And this would then be used as

```<code>GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });
</code>```

This confronts me with the same issue I had before; the nameof(parameter), ofcourse, returns "parameter". I would also have to make a couple of extension methods for each type. Or check for the type in the extension method to make sure i get the correct value.

So, in short: how can i get the name of this variable that invokes the extension method?

答:
You could do the following "hack". Change the signature of your method to the following:

```<code>private static string GenericLog_Exception(
        Exception exceptionData,
        string extraInformation,
        params Expression<Func<object>>[] parameters)
</code>```

And now your call site would look a little bit cleaner:

```<code>GenericLog_Exception(ex,
                     "it's on fire, please help",
                     () => firstParam,
                     () => secondParam,
                     () => thirdParam);
</code>```

And you can extract parameter info from the expressions the following way (using C# tuple support for convenience):

```<code>private static (object Value, string ParamName) GetParameterInfo
    (Expression<Func<object>> expr)
{
    //First try to get a member expression directly.
    //If it fails we know there is a type conversion: parameter is not an object
    //(or we have an invalid lambda that will make us crash)
    //Get the "to object" conversion unary expression operand and then
    //get the member expression of that and we're set.
    var m = (expr.Body as MemberExpression) ??
            (expr.Body as UnaryExpression).Operand as MemberExpression;

    return (expr.Compile().Invoke(), m.Member.Name);
}
</code>```

Body:
I'm looking for a way to get hold of the name of a variable that was passed into an extensionmethod. I want to have the name of the parameter in the calling variable. Sounds strange, let me explain.

assume this piece of testing code

    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help");
        }
    }

On the last line you can see the exception being logged. I want to be able to provide optional parameter support. So the developers can add parameter information when needed.

I've seen many posts about this on stackoverflow, lot's of different approaches. Main thing is; it can't be done fully generically.

Some code for explanation:

    static string GetCallingMethodSignature()
    {
        StackTrace stackTrace = new StackTrace();

        // Get calling method name
        var callingMethod = stackTrace.GetFrame(1).GetMethod();
        var callingMethod_Name = callingMethod.Name;

        // get calling method params
        string retVal = string.Empty;

        var callingMethod_Parameters = callingMethod.GetParameters();

        retVal = callingMethod_Name + "(";
        foreach (var param in callingMethod_Parameters)
        {
            retVal += param.Name + ": " + param.ToString() + ",";
        }
        retVal.Remove(retVal.Length - 1, 1);
        retVal += ")";

        return retVal;
    }

Now, this testing code is getting the calling method name and it's parameters. That is, the names of the parameters. But not their values. The param.tostring() part only returns the type name. Not the value. I've been reading on this and it seems this can't be done via reflection.

So then I went for another approach, why not provide the parameters the developer finds suitable for logging. You don't need all of them most of the time anyway.

private static string GenericLog_Exception(Exception exceptionData, string extraInformation, params KeyValuePair<string, object>[] parameters)

So, this being a new testmethod, i'm providing the parameters of choice into the exception logging method. But if you want to make this work, it's one hell of a job everytime to make this call.

    private static void TestingMethod(string firstParam, int secondParam, bool thirdParam)
    {
        try
        {
            throw new InvalidOperationException("This named optional params stuff, it's just not working boss");
        }
        catch (Exception ex)
        {
            GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[]{
                new KeyValuePair<string, object>("firstParam", firstParam),
                new KeyValuePair<string, object>("secondParam", secondParam),
                new KeyValuePair<string, object>("thirdParam", thirdParam)
            });
        }
    }

Now this is working. But as said, i find the bottom part to cumbersome. I was thinking along the lines of an extensionmethod, so I can shorten the creation of each kvp.

internal static class ExtensionMethodsForTesting
{
    internal static KeyValuePair<string, object> AsKeyValuePair(this string parameter)
    {
        var name = nameof(parameter);
        return new KeyValuePair<string, object>(name, parameter);
    }
}

And this would then be used as

GenericLog_Exception(ex, "it's on fire, please help", new KeyValuePair<string, object>[] { firstParam.AsKeyValuePair() });

This confronts me with the same issue I had before; the nameof(parameter), ofcourse, returns "parameter". I would also have to make a couple of extension methods for each type. Or check for the type in the extension method to make sure i get the correct value.

So, in short: how can i get the name of this variable that invokes the extension method?

Body:
You could do the following "hack". Change the signature of your method to the following:

private static string GenericLog_Exception(
        Exception exceptionData,
        string extraInformation,
        params Expression<Func<object>>[] parameters)

And now your call site would look a little bit cleaner:

GenericLog_Exception(ex,
                     "it's on fire, please help",
                     () => firstParam,
                     () => secondParam,
                     () => thirdParam);

And you can extract parameter info from the expressions the following way (using C# tuple support for convenience):

private static (object Value, string ParamName) GetParameterInfo
    (Expression<Func<object>> expr)
{
    //First try to get a member expression directly.
    //If it fails we know there is a type conversion: parameter is not an object
    //(or we have an invalid lambda that will make us crash)
    //Get the "to object" conversion unary expression operand and then
    //get the member expression of that and we're set.
    var m = (expr.Body as MemberExpression) ??
            (expr.Body as UnaryExpression).Operand as MemberExpression;

    return (expr.Compile().Invoke(), m.Member.Name);
}


问:
How to solve it ( EXC_BAD_ADDRESS in Objective-C )?
sometimes, fatal error occurs in my app with EXC_BAD_ADDRESS error log.

What is the cause of my code?

crash log

```<code>0. Crashed: GGMutableDictionary Isolation Queue
0  libobjc.A.dylib                0x184e2c150 objc_msgSend + 16
1  CoreFoundation                 0x1862e0d04 -[NSDictionary descriptionWithLocale:indent:] + 916
2  CoreFoundation                 0x1862e0dac -[NSDictionary descriptionWithLocale:indent:] + 1084
3  Foundation                     0x186da35a4 _NSDescriptionWithLocaleFunc + 76
4  CoreFoundation                 0x1863788bc __CFStringAppendFormatCore + 8440
5  CoreFoundation                 0x18637678c _CFStringCreateWithFormatAndArgumentsAux2 + 244
6  Foundation                     0x186da3418 +[NSString stringWithFormat:] + 68
7  app                            0x10019f4b8 -[TinyDB saveAsync] + 4296963256
8  app                            0x10019c86c __26-[TinyDB putString:value:]_block_invoke + 4296951916
9  libdispatch.dylib              0x18526e9a0 _dispatch_client_callout + 16
10 libdispatch.dylib              0x18527bee0 _dispatch_barrier_sync_f_invoke + 84
11 app                            0x10019c7e0 -[TinyDB putString:value:] + 4296951776
</code>```

source file

This class is used asynchronously from many other class.
This class should have thread safe. But EXC_BAD_ADDRESS fatal error occurs in saveAsync method.
I think weakDictionaryRef or isolationQueue variables are deallocated. I want to fix this problem. What should I fix in this code?
Thank you for your advice.

TinyDB.h file

```<code>@interface TinyDB : NSObject

@property (nonatomic, retain) NSString * docPath;
// @property (nonatomic, retain) NSMutableDictionary * dictionary;
@property (nonatomic, retain) NSFileManager * fileManager;
@property (nonatomic, retain) NSString * dir;
@property (nonatomic, assign) BOOL flagWrite;
- (instancetype)initWithFile:(NSString *)file;
- (NSString *)getDocPath;
- (void)putDouble:(NSString *)key value:(double)value;
- (void)putInt:(NSString *)key value:(NSInteger)value;
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value;
- (void)putString:(NSString *)key value:(NSString *)value;
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value;
- (void)putLong:(NSString *)key value:(NSInteger)value;
- (void)putBool:(NSString *)key value:(BOOL)value;
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value;
- (id)get:(NSString *)key;
- (NSMutableArray *)getMutableArray:(NSString *)key;
- (BOOL)has:(NSString *)key;
- (void)saveAsync;
- (void)save;
- (NSString *)jsonString;
- (NSString *)stringify:(id)obj;
- (NSString *)getSet:(id)value;
- (NSString *)getPairSet:(NSString *)key value:(id)value;
- (NSMutableDictionary*)getMutableDictionary:(NSString*)key;
- (NSString *)getString:(NSString *)key;
- (BOOL)getBool:(NSString*)key;
- (NSArray *)allKeys;
- (void)removeObjectForKey:(NSString*)key;
@end
</code>```

TinyDB.m  file

```<code>@implementation TinyDB
{
@private dispatch_queue_t isolationQueue_;
@private __strong NSMutableDictionary * _myDictionary;
}
@synthesize docPath=docPath,fileManager=fileManager,dir=dir,flagWrite=flagWrite;
BOOL flagOnSave = false;
BOOL flagWrite = true;
NSString* dir;
NSString* docPath = @"";
NSLock* _dicLock=nil;
NSFileManager* fileManager;
__weak id _weakDictionaryRef;

-(id)initWithFile:(NSString *)file{
    self = [super init];
    docPath = file;
    // ##########################################
     isolationQueue_ = dispatch_queue_create([@"GGMutableDictionary Isolation Queue" UTF8String], DISPATCH_QUEUE_CONCURRENT);
    // ##########################################
    fileManager = [NSFileManager defaultManager];
    dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) firstObject];
    dir = [NSString stringWithFormat:@"%@/myapp/",dir];
    BOOL flagFileExist = [fileManager fileExistsAtPath:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
    _myDictionary = [[NSMutableDictionary alloc] init];
    if(flagFileExist){
        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Found!!! %@ --> ",file]];
        @try{
            NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
            _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:dic];
        }@catch(NSException * e){
            _myDictionary = [[NSMutableDictionary alloc] init];
        }@finally{
        }
    }else{
        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Not Found!!!--> %@ ",file]];
        _myDictionary = [[NSMutableDictionary alloc] init];
    }
    _weakDictionaryRef = _myDictionary;
    [self saveAsync];
    return self;
}
-(void)putString:(NSString*)key value:(NSString*)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        if(value == nil){
            return;
        }
        @try{
            [_myDictionary setObject:value forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            dispatch_barrier_sync(isolationQueue_, ^{
                [_myDictionary setObject:value forKey:key];
            });
        }@finally{
        }
        [self saveAsync];
    });
}

- (void)putDouble:(NSString *)key value:(double)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithDouble:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putInt:(NSString *)key value:(NSInteger)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        @try{
            [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        }@finally{
        }
        [self saveAsync];
    });
}
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        if( key != nil && value != nil ){
            [_myDictionary setObject:value forKey:key];
            [self saveAsync];
        }
    });
}
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        TinyDB* db = value;
        NSString* docuPath = [db getDocPath];
        @try{
            [_myDictionary setObject:docuPath forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            dispatch_barrier_sync(isolationQueue_, ^{
                [_myDictionary setObject:docuPath forKey:key];
            });
        }@finally{

        }
        [self saveAsync];
    });
}
- (void)putLong:(NSString *)key value:(NSInteger)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putBool:(NSString *)key value:(BOOL)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithBool:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:value forKey:key];
        [self saveAsync];
    });
}
-(void)removeObjectForKey:(NSString*)key{
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil && [_myDictionary objectForKey:key] != nil ){
            [_myDictionary removeObjectForKey:key];
        }
    });
}
-(void) save{
    dispatch_barrier_sync(isolationQueue_, ^{
        @try {
            // NSLog([NSString stringWithFormat:@"writeToFile Error : orgPath = %@/%@.myapp / %@",dir,docPath, self.dictionary ]);
            // NSMutableDictionary* nsDic = self.dictionary;
            if( _myDictionary != nil ){
                NSDictionary * _dictionary =
                (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                       (__bridge CFPropertyListRef)(_myDictionary),
                                                                       kCFPropertyListImmutable));
                if( _dictionary != nil ){
                    [_dictionary writeToFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]  atomically: false];
                }
            }
        }@catch (NSException *exception) {
            _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _weakDictionaryRef = _myDictionary;
        }@finally {
        }
    });
}
// ################################################################
// normal function
- (NSString *)jsonString{
    __block NSString* buff = @"";
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil ){
            NSDictionary * _dictionary = nil;
            // dispatch_barrier_sync(isolationQueue_, ^{
            _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                                (__bridge CFPropertyListRef)(_myDictionary),
                                                                                kCFPropertyListImmutable));
            if( _dictionary != nil ){
                buff = [self stringify:_dictionary];
            }
        }else{
            NSLog(@"buff = [self stringify:_myDictionary]; is nil ");
        }

    });
    return buff;
}
- (NSString *)stringify:(id)obj{
    if([obj isKindOfClass:[NSDictionary class]]){
        int idx = 0;
        NSString* buff = @"{";
        if( obj != nil ){
            NSDictionary* dic = [NSDictionary dictionaryWithDictionary:obj]; //obj;
            for(NSString* key in dic){
                id value = [dic objectForKey:key];
                if(idx != 0){
                    buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
                }
                buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getPairSet:key value:value]];
                idx++;
            }
        }
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"}"];
        return buff;
    }else if([obj isKindOfClass:[NSArray class]]){
        int idx = 0;
        NSString* buff = @"[";
        if( obj != nil ){
            NSMutableArray* _a = [[NSMutableArray alloc] init];
            for( int ai = 0; ai < [obj count]; ai++){
                if( [obj objectAtIndex:ai] != nil ){
                    [_a addObject:[obj objectAtIndex:ai]];
                }
            }
            NSArray* arr = [NSArray arrayWithArray:_a]; //obj;
            for(id value in arr){
                if(idx != 0){
                    buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
                }
                buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getSet:value]];
                idx++;
            }
        }
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"]"];
        return buff;
    }else{
        return [self getSet:obj];
    }
}
- (NSString *)getSet:(id)value{
    NSString* buff = @"";
    if([value isKindOfClass:[NSString class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\"",buff,value];
    }else if([value isKindOfClass:[NSNumber class]]){
        NSNumber* val = value;
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[val stringValue]];
    }else{
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self stringify:value]];
    }
    return buff;
}
- (NSString *)getPairSet:(NSString *)key value:(id)value{
    NSString* buff = @"";
    if([value isKindOfClass:[NSString class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":\"%@\"",buff,key,value];
    }else if([value isKindOfClass:[NSNumber class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[value stringValue]];
    }else{
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[self stringify:value]];
    }
    return buff;
}
-(NSMutableDictionary*)getMutableDictionary:(NSString*)key{
    NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
    id obj = [_myDictionary objectForKey:key];
    if(obj != nil){
        dic = [[NSMutableDictionary alloc] initWithDictionary:obj];
    }
    return dic;
}
-(NSArray *)allKeys{
    __block NSArray* arr = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil ){
            arr = [_myDictionary allKeys];
        }
    });
    return arr;
}
- (NSString *)getDocPath{
    return docPath;
}
- (id)get:(NSString *)key{
    __block id _obj = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        _obj = [_myDictionary objectForKey:key];
    });
    return _obj;
}
- (NSString *)getString:(NSString *)key{
    __block NSString* returnStr = @"";
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key]==nil){
            returnStr = @"";
        }
        if([[_myDictionary objectForKey:key] isKindOfClass:[NSString class]]){
            returnStr = [_myDictionary objectForKey:key];
        }else{
            returnStr = @"";
        }
    });
    return returnStr;
}
- (BOOL)getBool:(NSString*)key{
    __block BOOL flag = false;
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key]==nil){
            flag = NO;
        }
        if([[_myDictionary objectForKey:key] isKindOfClass:[NSNumber class]]){
            NSNumber* boolValue = [_myDictionary objectForKey:key];
            if([boolValue boolValue] == YES){
                flag = YES;
            }else{
                flag = NO;
            }
        }else{
            flag = NO;
        }
    });
    return flag;
}
- (NSMutableArray *)getMutableArray:(NSString *)key{
    __block NSMutableArray* _arr = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        _arr =  [_myDictionary objectForKey:key];
    });
    return _arr;
}
- (BOOL)has:(NSString *)key{
    __block BOOL flag = false;
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key] != nil){
            flag = true;
        }else{
            flag = false;
        }
    });
    return flag;
}
// #########################
// save function
int flagTest = 0;
bool mark = 0;
NSTimer* saveTimer = nil;
-(void)saveAsync{
    @try {
        [BSDebugger log:[NSString stringWithFormat:@"_weakDictionaryRef : %@ ",_weakDictionaryRef ]];
        if( _myDictionary != nil ){
            if( _weakDictionaryRef != nil ){
                NSDictionary * _dictionary = nil;
                _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                                (__bridge CFPropertyListRef)(_myDictionary),
                                                                                kCFPropertyListImmutable));
                @try{
                    flagOnSave = true;
                    UIBackgroundTaskIdentifier taskID = [myappCore beginBackgroundUpdateTask];
                    flagWrite = false;
                    NSString* orgPath = [[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath ];
                    @try {
                        if( _dictionary != nil ){
                            [_dictionary writeToFile:orgPath atomically:YES];
                        }
                    }@catch (NSException *exception) {
                        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exception callStackSymbols]]];
                    }@finally {
                    }
                    flagWrite = true;
                    flagOnSave = false;
                    [myappCore endBackgroundUpdateTask:taskID];
                }@catch (NSException *exceptionMain) {
                    [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exceptionMain callStackSymbols]]];
                }@finally {
                    _dictionary = nil;
                }
                return;
                // });
            }
        }
    }@catch (NSException *exception) {
    }@finally {
        // [_dicLock unlock];
    }
}
@end
</code>```

答:
Some ideas:

Turn on zombies (How to enable NSZombie in Xcode). You'll get more information about the object causing the crash when you do that.

If you can make the error happen at will, set a breakpoint at the top of saveAsync and step through it.

Change the stringWithFormat calls somehow so they don't reference anything that might be deallocated and see if the problem goes away. If it does, you'll know what was causing it.

I find it sometimes helps to override retain and release in objects I'm suspicious of and either print something out or set a breakpoint so I can see who might be over-releasing an object.

Body:
sometimes, fatal error occurs in my app with EXC_BAD_ADDRESS error log.

What is the cause of my code?

crash log

0. Crashed: GGMutableDictionary Isolation Queue
0  libobjc.A.dylib                0x184e2c150 objc_msgSend + 16
1  CoreFoundation                 0x1862e0d04 -[NSDictionary descriptionWithLocale:indent:] + 916
2  CoreFoundation                 0x1862e0dac -[NSDictionary descriptionWithLocale:indent:] + 1084
3  Foundation                     0x186da35a4 _NSDescriptionWithLocaleFunc + 76
4  CoreFoundation                 0x1863788bc __CFStringAppendFormatCore + 8440
5  CoreFoundation                 0x18637678c _CFStringCreateWithFormatAndArgumentsAux2 + 244
6  Foundation                     0x186da3418 +[NSString stringWithFormat:] + 68
7  app                            0x10019f4b8 -[TinyDB saveAsync] + 4296963256
8  app                            0x10019c86c __26-[TinyDB putString:value:]_block_invoke + 4296951916
9  libdispatch.dylib              0x18526e9a0 _dispatch_client_callout + 16
10 libdispatch.dylib              0x18527bee0 _dispatch_barrier_sync_f_invoke + 84
11 app                            0x10019c7e0 -[TinyDB putString:value:] + 4296951776

source file

This class is used asynchronously from many other class.
This class should have thread safe. But EXC_BAD_ADDRESS fatal error occurs in saveAsync method.
I think weakDictionaryRef or isolationQueue variables are deallocated. I want to fix this problem. What should I fix in this code?
Thank you for your advice.

TinyDB.h file

@interface TinyDB : NSObject

@property (nonatomic, retain) NSString * docPath;
// @property (nonatomic, retain) NSMutableDictionary * dictionary;
@property (nonatomic, retain) NSFileManager * fileManager;
@property (nonatomic, retain) NSString * dir;
@property (nonatomic, assign) BOOL flagWrite;
- (instancetype)initWithFile:(NSString *)file;
- (NSString *)getDocPath;
- (void)putDouble:(NSString *)key value:(double)value;
- (void)putInt:(NSString *)key value:(NSInteger)value;
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value;
- (void)putString:(NSString *)key value:(NSString *)value;
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value;
- (void)putLong:(NSString *)key value:(NSInteger)value;
- (void)putBool:(NSString *)key value:(BOOL)value;
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value;
- (id)get:(NSString *)key;
- (NSMutableArray *)getMutableArray:(NSString *)key;
- (BOOL)has:(NSString *)key;
- (void)saveAsync;
- (void)save;
- (NSString *)jsonString;
- (NSString *)stringify:(id)obj;
- (NSString *)getSet:(id)value;
- (NSString *)getPairSet:(NSString *)key value:(id)value;
- (NSMutableDictionary*)getMutableDictionary:(NSString*)key;
- (NSString *)getString:(NSString *)key;
- (BOOL)getBool:(NSString*)key;
- (NSArray *)allKeys;
- (void)removeObjectForKey:(NSString*)key;
@end

TinyDB.m  file

@implementation TinyDB
{
@private dispatch_queue_t isolationQueue_;
@private __strong NSMutableDictionary * _myDictionary;
}
@synthesize docPath=docPath,fileManager=fileManager,dir=dir,flagWrite=flagWrite;
BOOL flagOnSave = false;
BOOL flagWrite = true;
NSString* dir;
NSString* docPath = @"";
NSLock* _dicLock=nil;
NSFileManager* fileManager;
__weak id _weakDictionaryRef;

-(id)initWithFile:(NSString *)file{
    self = [super init];
    docPath = file;
    // ##########################################
     isolationQueue_ = dispatch_queue_create([@"GGMutableDictionary Isolation Queue" UTF8String], DISPATCH_QUEUE_CONCURRENT);
    // ##########################################
    fileManager = [NSFileManager defaultManager];
    dir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true) firstObject];
    dir = [NSString stringWithFormat:@"%@/myapp/",dir];
    BOOL flagFileExist = [fileManager fileExistsAtPath:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
    _myDictionary = [[NSMutableDictionary alloc] init];
    if(flagFileExist){
        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Found!!! %@ --> ",file]];
        @try{
            NSMutableDictionary* dic = [[NSMutableDictionary alloc] initWithContentsOfFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]];
            _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:dic];
        }@catch(NSException * e){
            _myDictionary = [[NSMutableDictionary alloc] init];
        }@finally{
        }
    }else{
        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_CONFIG : File Not Found!!!--> %@ ",file]];
        _myDictionary = [[NSMutableDictionary alloc] init];
    }
    _weakDictionaryRef = _myDictionary;
    [self saveAsync];
    return self;
}
-(void)putString:(NSString*)key value:(NSString*)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        if(value == nil){
            return;
        }
        @try{
            [_myDictionary setObject:value forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            dispatch_barrier_sync(isolationQueue_, ^{
                [_myDictionary setObject:value forKey:key];
            });
        }@finally{
        }
        [self saveAsync];
    });
}

- (void)putDouble:(NSString *)key value:(double)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithDouble:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putInt:(NSString *)key value:(NSInteger)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        @try{
            [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        }@finally{
        }
        [self saveAsync];
    });
}
- (void)putMutableArray:(NSString *)key value:(NSMutableArray *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        if( key != nil && value != nil ){
            [_myDictionary setObject:value forKey:key];
            [self saveAsync];
        }
    });
}
- (void)putTinyDB:(NSString *)key value:(TinyDB *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        TinyDB* db = value;
        NSString* docuPath = [db getDocPath];
        @try{
            [_myDictionary setObject:docuPath forKey:key];
        }@catch(NSException* e){
            NSMutableDictionary* buff = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _myDictionary = buff;
            _weakDictionaryRef = _myDictionary;
            dispatch_barrier_sync(isolationQueue_, ^{
                [_myDictionary setObject:docuPath forKey:key];
            });
        }@finally{

        }
        [self saveAsync];
    });
}
- (void)putLong:(NSString *)key value:(NSInteger)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithInteger:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putBool:(NSString *)key value:(BOOL)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:[[NSNumber alloc] initWithBool:value] forKey:key];
        [self saveAsync];
    });
}
- (void)putDictionary:(NSString *)key value:(NSDictionary *)value{
    dispatch_barrier_sync(isolationQueue_, ^{
        [_myDictionary setObject:value forKey:key];
        [self saveAsync];
    });
}
-(void)removeObjectForKey:(NSString*)key{
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil && [_myDictionary objectForKey:key] != nil ){
            [_myDictionary removeObjectForKey:key];
        }
    });
}
-(void) save{
    dispatch_barrier_sync(isolationQueue_, ^{
        @try {
            // NSLog([NSString stringWithFormat:@"writeToFile Error : orgPath = %@/%@.myapp / %@",dir,docPath, self.dictionary ]);
            // NSMutableDictionary* nsDic = self.dictionary;
            if( _myDictionary != nil ){
                NSDictionary * _dictionary =
                (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                       (__bridge CFPropertyListRef)(_myDictionary),
                                                                       kCFPropertyListImmutable));
                if( _dictionary != nil ){
                    [_dictionary writeToFile:[[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath]  atomically: false];
                }
            }
        }@catch (NSException *exception) {
            _myDictionary = [[NSMutableDictionary alloc] initWithDictionary:_myDictionary];
            _weakDictionaryRef = _myDictionary;
        }@finally {
        }
    });
}
// ################################################################
// normal function
- (NSString *)jsonString{
    __block NSString* buff = @"";
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil ){
            NSDictionary * _dictionary = nil;
            // dispatch_barrier_sync(isolationQueue_, ^{
            _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                                (__bridge CFPropertyListRef)(_myDictionary),
                                                                                kCFPropertyListImmutable));
            if( _dictionary != nil ){
                buff = [self stringify:_dictionary];
            }
        }else{
            NSLog(@"buff = [self stringify:_myDictionary]; is nil ");
        }

    });
    return buff;
}
- (NSString *)stringify:(id)obj{
    if([obj isKindOfClass:[NSDictionary class]]){
        int idx = 0;
        NSString* buff = @"{";
        if( obj != nil ){
            NSDictionary* dic = [NSDictionary dictionaryWithDictionary:obj]; //obj;
            for(NSString* key in dic){
                id value = [dic objectForKey:key];
                if(idx != 0){
                    buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
                }
                buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getPairSet:key value:value]];
                idx++;
            }
        }
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"}"];
        return buff;
    }else if([obj isKindOfClass:[NSArray class]]){
        int idx = 0;
        NSString* buff = @"[";
        if( obj != nil ){
            NSMutableArray* _a = [[NSMutableArray alloc] init];
            for( int ai = 0; ai < [obj count]; ai++){
                if( [obj objectAtIndex:ai] != nil ){
                    [_a addObject:[obj objectAtIndex:ai]];
                }
            }
            NSArray* arr = [NSArray arrayWithArray:_a]; //obj;
            for(id value in arr){
                if(idx != 0){
                    buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@","];
                }
                buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self getSet:value]];
                idx++;
            }
        }
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,@"]"];
        return buff;
    }else{
        return [self getSet:obj];
    }
}
- (NSString *)getSet:(id)value{
    NSString* buff = @"";
    if([value isKindOfClass:[NSString class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\"",buff,value];
    }else if([value isKindOfClass:[NSNumber class]]){
        NSNumber* val = value;
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[val stringValue]];
    }else{
        buff = [[NSString alloc] initWithFormat:@"%@%@",buff,[self stringify:value]];
    }
    return buff;
}
- (NSString *)getPairSet:(NSString *)key value:(id)value{
    NSString* buff = @"";
    if([value isKindOfClass:[NSString class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":\"%@\"",buff,key,value];
    }else if([value isKindOfClass:[NSNumber class]]){
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[value stringValue]];
    }else{
        buff = [[NSString alloc] initWithFormat:@"%@\"%@\":%@",buff,key,[self stringify:value]];
    }
    return buff;
}
-(NSMutableDictionary*)getMutableDictionary:(NSString*)key{
    NSMutableDictionary* dic = [[NSMutableDictionary alloc] init];
    id obj = [_myDictionary objectForKey:key];
    if(obj != nil){
        dic = [[NSMutableDictionary alloc] initWithDictionary:obj];
    }
    return dic;
}
-(NSArray *)allKeys{
    __block NSArray* arr = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        if( _myDictionary != nil ){
            arr = [_myDictionary allKeys];
        }
    });
    return arr;
}
- (NSString *)getDocPath{
    return docPath;
}
- (id)get:(NSString *)key{
    __block id _obj = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        _obj = [_myDictionary objectForKey:key];
    });
    return _obj;
}
- (NSString *)getString:(NSString *)key{
    __block NSString* returnStr = @"";
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key]==nil){
            returnStr = @"";
        }
        if([[_myDictionary objectForKey:key] isKindOfClass:[NSString class]]){
            returnStr = [_myDictionary objectForKey:key];
        }else{
            returnStr = @"";
        }
    });
    return returnStr;
}
- (BOOL)getBool:(NSString*)key{
    __block BOOL flag = false;
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key]==nil){
            flag = NO;
        }
        if([[_myDictionary objectForKey:key] isKindOfClass:[NSNumber class]]){
            NSNumber* boolValue = [_myDictionary objectForKey:key];
            if([boolValue boolValue] == YES){
                flag = YES;
            }else{
                flag = NO;
            }
        }else{
            flag = NO;
        }
    });
    return flag;
}
- (NSMutableArray *)getMutableArray:(NSString *)key{
    __block NSMutableArray* _arr = nil;
    dispatch_barrier_sync(isolationQueue_, ^{
        _arr =  [_myDictionary objectForKey:key];
    });
    return _arr;
}
- (BOOL)has:(NSString *)key{
    __block BOOL flag = false;
    dispatch_barrier_sync(isolationQueue_, ^{
        if([_myDictionary objectForKey:key] != nil){
            flag = true;
        }else{
            flag = false;
        }
    });
    return flag;
}
// #########################
// save function
int flagTest = 0;
bool mark = 0;
NSTimer* saveTimer = nil;
-(void)saveAsync{
    @try {
        [BSDebugger log:[NSString stringWithFormat:@"_weakDictionaryRef : %@ ",_weakDictionaryRef ]];
        if( _myDictionary != nil ){
            if( _weakDictionaryRef != nil ){
                NSDictionary * _dictionary = nil;
                _dictionary = (__bridge NSDictionary *)(CFPropertyListCreateDeepCopy(kCFAllocatorDefault,
                                                                                (__bridge CFPropertyListRef)(_myDictionary),
                                                                                kCFPropertyListImmutable));
                @try{
                    flagOnSave = true;
                    UIBackgroundTaskIdentifier taskID = [myappCore beginBackgroundUpdateTask];
                    flagWrite = false;
                    NSString* orgPath = [[NSString alloc] initWithFormat:@"%@/%@.myapp",dir,docPath ];
                    @try {
                        if( _dictionary != nil ){
                            [_dictionary writeToFile:orgPath atomically:YES];
                        }
                    }@catch (NSException *exception) {
                        [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exception callStackSymbols]]];
                    }@finally {
                    }
                    flagWrite = true;
                    flagOnSave = false;
                    [myappCore endBackgroundUpdateTask:taskID];
                }@catch (NSException *exceptionMain) {
                    [BSDebugger log:[NSString stringWithFormat:@"DEBUG_myapp_TINYDB : %@",[exceptionMain callStackSymbols]]];
                }@finally {
                    _dictionary = nil;
                }
                return;
                // });
            }
        }
    }@catch (NSException *exception) {
    }@finally {
        // [_dicLock unlock];
    }
}
@end


问:
obj == null vs null == obj
I have always used to check for null like

```<code>if(null==obj)
</code>```

When I compiled my code and looked into .class file after decompiling, I could see that my code got changed to

```<code>if(obj==null)
</code>```

I know in java null==obj and obj==nulldoesn't matter. But I'm curious to know why compiler changed it?

答:
The compiler did not change anything. It faithfully compiled if (null == obj) and if (obj == null) into different bytecodes, which decompilers converted back to the same Java code.

Comparison with null on the right, i.e.

```<code>if (o == null) {
    ...
}
</code>```

gets translated to this byte code with ifnonnull instruction:

```<code>0: aload_0
1: ifnonnull     ...
</code>```

Comparison with null on the left, i.e.

```<code>if (null == o) {
    ...
}
</code>```

gets translated to a different bytecode with if_acmpne instruction:

```<code>0: aconst_null
1: aload_0
2: if_acmpne     ...
</code>```

In theory, decompiler has enough information to figure out which way the arguments are ordered in the source file. However, they produced the same code for both orderings.

Title: obj == null vs null == obj

Body:
I have always used to check for null like

if(null==obj)

When I compiled my code and looked into .class file after decompiling, I could see that my code got changed to

if(obj==null)

I know in java null==obj and obj==nulldoesn't matter. But I'm curious to know why compiler changed it?

Body:
The compiler did not change anything. It faithfully compiled if (null == obj) and if (obj == null) into different bytecodes, which decompilers converted back to the same Java code.

Comparison with null on the right, i.e.

if (o == null) {
    ...
}

gets translated to this byte code with ifnonnull instruction:

0: aload_0
1: ifnonnull     ...

Comparison with null on the left, i.e.

if (null == o) {
    ...
}

gets translated to a different bytecode with if_acmpne instruction:

0: aconst_null
1: aload_0
2: if_acmpne     ...

In theory, decompiler has enough information to figure out which way the arguments are ordered in the source file. However, they produced the same code for both orderings.


问:
Get remote address/IP - C Berkeley Sockets
If I have a socket file descriptor connected (either by connect or by bind), type SOCK_STREAM, is it possible to get the remote address / IP address?

I need to do this within a function where I don't have any other data than the socket file descriptor.

答: getpeername

Body: getpeername